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

Posted

技术标签:

【中文标题】TypeScript 3.0 `unknown` 类型作为 `any` 或 `generics` 的替代品?【英文标题】:TypeScript 3.0 `unknown` type as an alternative to `any` or `generics`? 【发布时间】:2019-01-05 06:20:00 【问题描述】:

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

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

例如,将上面的示例替换为使用unknown 而不是any 会强制将所有对 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();

我最近开始使用 TypeScript 进行编码,这是我的问题:

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

当然,用原生 javascript 编写的代码需要在 TypeScript 中自动使用 any 类型,但是当我们从头开始使用纯 TypeScript 编写代码时,是否有任何理由使用 any 类型而不是 unknown从 3.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');

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

谢谢。

【问题讨论】:

【参考方案1】:

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

function foo() :any  return 1; 
let x:string = foo () ;
x.bold() // runtime error

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

function foo() : unknown  return 1; 
let x:string = foo () ; // compile time error we need to think about why we are doing this. 

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

也许这 answer 关于两者之间的区别也有帮助

关于这种蜜蜂是泛型的替代品,它不是。首先你应该避免指定显式类型参数,大多数时候编译器会为你推断它们。

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)) 

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

例如您的A 示例:

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

 A1('').bold() //error return value is of type unknown

或者对于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

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

【讨论】:

非常感谢您提供的简明信息!。这很有帮助,我理解。 谢谢你们俩。我想了解未知和泛型之间的区别,这是完美的解释。

以上是关于TypeScript 3.0 `unknown` 类型作为 `any` 或 `generics` 的替代品?的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript 中 unknown 与 any 有啥区别

TypeScript 基础类型

微软TypeScript 3.0重磅发布!

typescript 基础类型

Vue 3.0前的 TypeScript 最佳入门实践

如何在 TypeScript 3.0 中使用项目引用?