& # 39;未知# 39;和& # 39;任何# 39;

TypeScript 3.0引入了unknown类型,根据他们的wiki:

unknown现在是一个保留类型名称,因为它现在是一个内置类型。 根据unknown的预期用途,可能需要删除 完全声明(支持新引入的未知类型),或者

unknownany有什么区别?什么时候我们应该使用unknown而不是any?

183059 次浏览

你可以在公关RC公告中阅读更多关于unknown的内容,但它的要点是:

(. .unknown,它是any的类型安全对应物。任何东西都可以赋值给unknown,但是unknown不能赋值给任何东西,只能赋值给它自己和没有类型断言或基于窄化的控制流的any。同样,如果不首先断言或缩小到更特定的类型,则不允许对未知类型进行任何操作。

举几个例子:

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

建议使用方法为:

很多时候,我们希望在TypeScript中描述功能最差的类型。这对于想要发出“这可以是任何值,所以在使用它之前必须执行某种类型的检查”信号的api非常有用。这迫使用户安全地自省返回的值。

unknown和any的区别如下:

很像any,任何值都可以赋值给unknown;然而,与any不同的是,您不能访问类型为unknown的值的任何属性,也不能调用/构造它们。此外,类型为unknown的值只能分配给unknownany

要回答你的问题,什么时候应该使用unknown而不是any:

这对于想要发出“这可以是任何值,所以 你必须执行一些类型的检查,然后再使用它”。这就迫使 用户安全地自省返回值

查看TypeScript 3.0公告,了解类型检查unknown类型变量的示例和更详细的解释。

# EYZ0类型:

any类型表示所有可能的JS值。每个类型都可以赋值给any类型。因此,any类型是类型系统的通用超类型。TS编译器将允许对any类型的值进行任何操作。例如:

let myVar: any;


myVar[0];
myVar();
myVar.length;
new myVar();

在很多情况下,这对TS编译器来说太宽松了。也就是说,它将允许我们已经知道会导致运行时错误的操作。

# EYZ0类型:

unknown类型表示(就像any一样)所有可能的JS值。每个类型都可以赋值给unknown类型。因此,unknown类型是类型系统的另一个通用超类型(与any并列)。然而,TS编译器不会允许对类型为unknown的值进行任何操作。此外,unknown类型只能赋值给any类型。下面的例子将说明这一点:

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

任何未知的:

  • 允许分配任何类型

任何:

  • 允许被分配给任何类型
  • 允许调用任何方法

无名:

  • 不允许被赋给任何类型
  • 不允许调用任何方法
const a: any = 'a'; // OK
const b: unknown = 'b' // OK


const v1: string = a; // OK
const v2: string = b; // ERROR
const v3: string = b as string; // OK


a.trim() // OK
b.trim() // ERROR

它们在语义上有所不同。

unknown是所有其他类型的父类型。它是类型系统中的常规类型。

any表示“关闭类型检查”。它是一个编译器指令和一种元编程。

未知的

如果编写的函数只将输入传递给另一个函数,请使用unknown。从函数的角度来看:“我不知道,我不想知道”。使用unknown没有任何问题。

例如:

function buy(item: unknown): Purchase {
if (item) {
return purchase(item);
} else {
throw new TypeError('item is missing');
}
}

任何

如果需要调用该值的属性,那么any更适合。

Linting可能不喜欢any,建议您的输入更具体。这样,如果您将接口从isItem更改为isValid, typescript会告诉您更新代码。

例如:

// 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;

如果你感兴趣,请参阅用户定义的防护,我带来了它,因为它是我需要的少数情况之一。

这篇来自ultimatecourses的博客:

如果没有其他选项,请使用any类型

很难找到any的好例子。

被接受的答案是“未知”,它是任何“未知”的类型安全对应物。

然而,正如这个例子所示,unknown是它自己的野兽,有时它的行为与any非常不同:

type Foo = unknown extends string ? true : false // false
type Bar = any extends string ? true : false     // boolean - i.e. both true and false

我是姗姗来迟,但我会尽力揭开它的神秘面纱。

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.

后者不会显示任何编译错误,但它会在运行时抛出错误,因为canNotBeAnything是一个数字类型,我们强制它为string

对于一个全面的概念,wy可以总结为blow吗? 任何带有来自所有类型的字段/函数 Unknown 给我们的只是普通的。

因此,提供:任何确保你将能够调用任何类型的特定函数/字段, 而调用:未知留给你的字段/方法很少,存在于每种类型中

Any == string|number|object|enum|function|等| .

Any == string|number|object Any是完整的联合类型 Unknown是任何的反船