TypeScript 3.0 `unknown` 类型作为 `any` 或 `generics` 的替代吗?

5 generics typescript

https://blogs.msdn.microsoft.com/typescript/2018/07/12/annoucing-typescript-3-0-rc/#the-unknown-type

TypeScript 3.0 引入了一种名为的新类型unknown,它正是这样做的。很像any,任何值都可以分配给unknown; 但是,与 不同的是any,您不能访问类型为值的任何属性unknown,也不能调用/构造它们。此外, type 的值unknown只能分配给unknownany

例如,将上面的示例交换为 useunknown而不是anyforce 会将 foo 的所有用法转换为错误:

let foo: unknown = 10;

// Since `foo` has type `unknown`, TypeScript
// errors on each of these usages.
foo.x.prop;
foo.y.prop;
foo.z.prop;
foo();
new foo();
upperCase(foo);
foo `hello world!`;

function upperCase(x: string) {
    return x.toUpperCase();
}
Run Code Online (Sandbox Code Playgroud)

我最近开始用 TypeScript 编写代码,这里是我的问题:

1. 在我看来,unknown可以完全替代any.

当然,用原生 JavaScript 编写的代码需要any在 TypeScript 中自动使用类型,但是当我们从头开始使用纯 TypeScript 编写代码时,是否有理由使用any类型而不是unknown3.0 版本?

2.什么是差异性之探源unknowngenerics

例如,

const A = <T>(value: T): T => value;
const A1 = (value: unknown) => value;

console.log(A<string>('Hello'), A<number>(100));



const B = <T, U>(t: T, u: U) => {
    console.log(t);
    console.log(u);
};
const B1 = (t: unknown, u: unknown) => {
    console.log(t);
    console.log(u);
};

B<string, number>('Hello', 100);
B<number, string>(100, 'Hello');
Run Code Online (Sandbox Code Playgroud)

并假设参数value: unknown最初是明确键入的,值的类型已确定,因此在我看来没有理由T明确传递。

谢谢。

Tit*_*mir 8

关于您问题的第一部分,我可能会在大多数情况下使用unknown而不是any在必要时使用明确的断言,以使程序员意识到某些事情不一定安全。一个大问题any是人们在不知不觉中将其分配给预期错误的类型变量或参数:

function foo() :any { return 1;} 
let x:string = foo () ;
x.bold() // runtime error
Run Code Online (Sandbox Code Playgroud)

使用上述任何代码都会导致运行时错误

function foo() : unknown { return 1;} 
let x:string = foo () ; // compile time error we need to think about why we are doing this. 
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,我们将不得不使用显式断言来使其工作,并考虑为什么我们将结果断言foo为字符串

也许这个关于两者之间差异的答案也有帮助

关于这个作为泛型的替代品,它不是。首先,您应该避免指定显式类型参数,大多数情况下编译器会为您推断它们。

const A = <T>(value: T): T => value;
const A1 = (value: unknown) => value;

// redundant and a lot of typing 
console.log(A<string>('Hello'), A<number>(100));
// let the compiler do the work for us
console.log(A('Hello'), A(100)) 
Run Code Online (Sandbox Code Playgroud)

如果您仅在一个位置使用泛型参数(即用于单个参数或用于返回值),则不会显示泛型的威力,而是当您使用它来指定两个或多个之间的关系时。

例如你的A例子:

 A('').bold() // ok return is the same as the parameter type

 A1('').bold() //error return value is of type unknown
Run Code Online (Sandbox Code Playgroud)

或者因为B我们可以指定参数必须是相同类型

const B = <T>(t: T, u: T) => {
    console.log(t);
    console.log(u);
};
const B1 = (t: unknown, u: unknown) => {
    console.log(t);
    console.log(u);
};

B('Hello', 100); //compile time error 
B1(100, 'Hello'); //compiles
Run Code Online (Sandbox Code Playgroud)

此外,泛型参数可以有额外的约束,因此并非所有类型都对给定的类型参数有效。