typescript “未知”与“任何”

niwlg2el  于 2023-03-31  发布在  TypeScript
关注(0)|答案(9)|浏览(131)

TypeScript 3.0引入了unknown类型,根据他们的wiki:
unknown现在是一个保留的类型名称,因为它现在是一个内置类型。根据你对unknown的预期使用,你可能希望完全删除声明(支持新引入的unknown类型),或者将其重命名为其他类型。
unknownany有什么区别?什么时候应该使用unknown而不是any

cu6pst1q

cu6pst1q1#

您可以在PRRC announcement中阅读有关unknown的更多信息,但其要点是:
[..]unknown是any的类型安全对应物。任何东西都可以分配给unknown,但是unknown不能分配给任何东西,除了它自己和任何没有类型Assert或基于控制流的收缩的东西。同样,在没有首先Assert或收缩到更具体的类型之前,不允许对unknown进行任何操作。
举几个例子:

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很有用。这迫使用户安全地内省返回值。

4ktjp1zp

4ktjp1zp2#

它们在语义上是不同的。
unknown是所有其他类型的父类型。它是类型系统中的常规类型。
any的意思是“关闭类型检查”。这是一个编译器指令,也是一种 meta编程。

pw9qyyiw

pw9qyyiw3#

unknown和any的区别如下:
就像any一样,任何值都可以分配给unknown;但是,与any不同,您不能访问unknown类型的值的任何属性,也不能调用/构造它们。此外,unknown类型的值只能分配给unknownany
要回答您关于何时应该使用unknown而不是any的问题,请执行以下操作:
这对于那些想要发出“这可以是任何值,所以你必须在使用它之前执行某种类型的检查”的API很有用。这迫使用户安全地内省返回的值。
查看TypeScript 3.0 announcement,了解unknown类型变量的类型检查示例和更详细的解释。

pdkcd3nj

pdkcd3nj4#

any类型:

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

let myVar: any;

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

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

unknown类型:

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

zu0ti5jz5#

任何,未知:

  • 允许分配任何类型

任何:

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

未知:

  • 不允许分配给任何类型
  • 不允许调用任何方法
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
new9mtju

new9mtju6#

未知

如果你写了一个函数,只将一个输入传递给另一个函数,使用unknown。从函数的Angular 来看:“我不知道,我不想知道”。使用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的好例子。

ncgqoxb0

ncgqoxb07#

我来晚了,但我会努力澄清它。

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

pu82cl6c

pu82cl6c8#

公认的答案是“未知哪个是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
nom7f22z

nom7f22z9#

下面是很容易区分anyunknown的方法。

什么是常见

您可以将任何内容分配给any,也可以将任何内容分配给unknown

let anyVar: any = 'Value';         // OK
anyVar = 3;                        // OK
let unknownVar: unknown = 'Value'; // OK
unknownVar = 3;                    // OK

观看演示

有什么不同

您可以对any执行任何操作,但必须进行类型检查或类型Assert才能对unknown进行操作
一个二个一个一个
观看演示
也检查后"unknown vs any in TypeScript"(我是文章的作者)。

相关问题