let vAny: any = 10; // We can assign anything to any
let vUnknown: unknown = 10; // We can assign anything to unknown just like any
let s1: string = vAny; // Any is assignable to anything
let s2: string = vUnknown; // Invalid; we can't assign vUnknown to any other type (without an explicit assertion)
vAny.method(); // Ok; anything goes with any
vUnknown.method(); // Not ok; we don't know anything about this variable
let myVar: unknown;
let myVar1: unknown = myVar; // No error
let myVar2: any = myVar; // No error
let myVar3: boolean = myVar; // Type 'unknown' is not assignable to type 'boolean'
// The following operations on myVar all give the error:
// Object is of type 'unknown'
myVar[0];
myVar();
myVar.length;
new myVar();
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function isItem(item: any): item is Purchase {
return !!item?.price;
}
调用属性
function isStuff(item: unknown): item is Stuff {
return (item as Stuff).it !== undefined;
}
function isStuff(item: any): item is Stuff {
return item.it !== undefined;
}
camelcaseKeys(item) as unknown as Item;
const canBeAnything: any = 100;
const canNotBeAnything: unknown = 100;
// If we try to use a .startsWith() method
canBeAnything.startsWith('10'); // no error
canNotBeAnything.startsWith('10'); // Property 'startsWith' does not exist on type 'unknown'
在unknown上使用方法.startsWith()的唯一方法是显式地告诉编译器类型,如
(canNotBeAnything as string).startsWith('10'); // Chill down TS compiler, I know what I am doing.
9条答案
按热度按时间cu6pst1q1#
您可以在PR或RC announcement中阅读有关
unknown
的更多信息,但其要点是:[..]unknown是any的类型安全对应物。任何东西都可以分配给unknown,但是unknown不能分配给任何东西,除了它自己和任何没有类型Assert或基于控制流的收缩的东西。同样,在没有首先Assert或收缩到更具体的类型之前,不允许对unknown进行任何操作。
举几个例子:
建议的用法是:
我们经常希望在TypeScript中描述功能最差的类型。这对于那些希望发出“这可以是任何值,因此您必须在使用它之前执行某种类型的检查”信号的API很有用。这迫使用户安全地内省返回值。
4ktjp1zp2#
它们在语义上是不同的。
unknown
是所有其他类型的父类型。它是类型系统中的常规类型。any
的意思是“关闭类型检查”。这是一个编译器指令,也是一种 meta编程。pw9qyyiw3#
unknown和any的区别如下:
就像
any
一样,任何值都可以分配给unknown
;但是,与any
不同,您不能访问unknown
类型的值的任何属性,也不能调用/构造它们。此外,unknown
类型的值只能分配给unknown
或any
。要回答您关于何时应该使用
unknown
而不是any
的问题,请执行以下操作:这对于那些想要发出“这可以是任何值,所以你必须在使用它之前执行某种类型的检查”的API很有用。这迫使用户安全地内省返回的值。
查看TypeScript 3.0 announcement,了解
unknown
类型变量的类型检查示例和更详细的解释。pdkcd3nj4#
any
类型:any
类型表示所有可能的JS值。每个类型都可以分配给类型any
。因此类型any
是类型系统的通用超类型。TS编译器将允许对类型any
的值进行任何操作。例如:在许多情况下,这对TS编译器来说太宽松了。也就是说,它将允许我们可能已经知道会导致运行时错误的操作。
unknown
类型:unknown
类型表示(就像any
一样)所有可能的JS值。每个类型都可以赋值给类型unknown
。因此类型unknown
是类型系统的另一个通用超类型(any
旁边)。但是TS编译器不会允许对类型为unknown
的值进行任何操作。此外,unknown
类型只能分配给any
类型。下面的例子将说明这一点:zu0ti5jz5#
任何,未知:
任何:
未知:
new9mtju6#
未知
如果你写了一个函数,只将一个输入传递给另一个函数,使用
unknown
。从函数的Angular 来看:“我不知道,我不想知道”。使用unknown
没有什么错。例如:
任意
如果需要调用该值的属性,那么
any
更适合。Linting可能不喜欢
any
,建议您输入更具体。这样,如果您将接口从isItem
更改为isValid
,typescript会告诉您更新代码。例如:
调用属性
如果你感兴趣的话,可以看看用户定义的守卫,我把它带进来是因为它是我需要的少数情况之一。
来自ultimatecourses的博客:
如果没有其他选项,请使用
any
类型很难找到
any
的好例子。ncgqoxb07#
我来晚了,但我会努力澄清它。
在unknown上使用方法
.startsWith()
的唯一方法是显式地告诉编译器类型,如后者不会显示任何编译错误,但会在运行时抛出错误,因为
canNotBeAnything
是一个数字类型,我们强制它为string
pu82cl6c8#
公认的答案是“未知哪个是any的类型安全对应物”。
然而,正如这个例子所示,
unknown
是它自己的野兽,有时它的行为与any
非常不同:nom7f22z9#
下面是很容易区分
any
和unknown
的方法。什么是常见
您可以将任何内容分配给
any
,也可以将任何内容分配给unknown
。观看演示
有什么不同
您可以对
any
执行任何操作,但必须进行类型检查或类型Assert才能对unknown
进行操作。一个二个一个一个
观看演示
也检查后"unknown vs any in TypeScript"(我是文章的作者)。