'未知'与'任何'

Jac*_*law 114 typescript typescript3.0

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

unknown现在是一个保留类型名称,因为它现在是一个内置类型.根据您对未知的预期用途,您可能希望完全删除声明(支持新引入的未知类型),或将其重命名为其他类型.

unknown和之间有什么区别any?我们什么时候使用unknownany

Zim*_*Zim 158

它们在语义上是不同的。

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

any意思是“禁用类型检查”。这是一个编译器指令。

  • 这些简单的句子意义重大。 (28认同)

Tit*_*mir 152

您可以unknownPRRC公告中阅读更多相关内容,但其主旨是:

[..]未知哪个是任何类型安全的对应物.任何东西都可以分配给未知,但是未知的东西除了本身以及任何没有类型断言或基于控制流的缩小之外的任何东西都不能分配.同样,如果没有先断言或缩小到更具体的类型,则不允许对未知操作进行操作.

一些例子:

let vAny: any = 10;          // We can assign anthing to any
let vUnknown: unknown =  10; // We can assign anthing to unknown just like any 


let s1: string = vAny;     // Any is assigable 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
Run Code Online (Sandbox Code Playgroud)

建议的用法是:

我们经常需要在TypeScript中描述功能最少的类型.这对于想要发出"可以是任何值,因此您必须在使用之前执行某种类型的检查"的API非常有用.这会强制用户安全地内省返回的值.

  • 我的理解是:“未知”是*我不知道*;“任何”是*我不在乎* (79认同)
  • 更详细地说,“未知”是*我还不知道,因此我必须弄清楚*,“任何”是*我不在乎,因此我不在乎* (50认同)
  • 任何来自C#背景的人,“ any”就像“ dynamic”,而“ unknown”就像“ object”。我喜欢`unknown`,因为它更安全。令人困惑的名字。 (12认同)
  • 我不知道这是否公平地比较 `unknown` 和 `object` @nawfal 虽然我认为我看到你在逆变和协方差方面得到了什么(例如任何对象都可以分配给类型 `object`尽管对于 `unknown` 可以分配任何对象或原语 - 类似地,`unknown` 可以分配给 `any` 或它本身,而 `object` 可以分配给 `dynamic` 或它本身)。附带说明一下,我不清楚为什么 TS 文档将 `unknown` 称为顶级类型,因为它并不真正包含所有类型 ¯\_(ツ)_/¯ (3认同)
  • 因此,对于“unknown”类型,您的代码必须先识别类型,然后才能访问该类型的任何成员,否则 TS 编译器会抱怨;对于类型“any”,编译器不会抱怨访问属性,即使该属性在运行时可能不存在? (2认同)

Awa*_*oof 23

unknown和any之间的区别描述如下:

很像any,任何价值都可以分配给unknown; 但是,any与之不同的是,您无法访问具有该类型的值的任何属性unknown,也无法调用/构造它们.此外,类型的值unknown只能分配给unknownany.

要回答你何时应该使用的unknown问题any:

这对于想要发出"可以是任何值,因此您必须在使用之前执行某种类型的检查"的API非常有用.这会强制用户安全地内省返回的值.

请查看TypeScript 3.0公告,了解类型检查类型变量的示例unknown和更详细的说明.


use*_*210 16

任何,未知:

  • 允许分配任何类型

任何:

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

未知:

  • 不允许分配给任何类型
  • 不允许调用任何方法
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
Run Code Online (Sandbox Code Playgroud)

  • `不允许调用任何方法`,这是不正确的(或者可能只是难以理解?)。无论如何,您可以对键入为“any”的值调用任何方法。 (3认同)
  • 显示使用“as T”的唯一答案,这会将类型从“unknown”更改为“T”。非常好。 (3认同)

eco*_*gic 15

未知

如果您编写的函数仅将输入传递给另一个函数,请使用unknown. 从功能的角度来看:“我不知道,我不想知道”。使用起来没有什么问题unknown

例如:

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

任何

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

Linting 可能不喜欢any,建议您更具体地输入您的内容。这样,如果您将界面从 更改为isItemisValid打字稿会告诉您更新代码。

例如:

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function isItem(item: any): item is Purchase {
  return !!item?.price;
}
Run Code Online (Sandbox Code Playgroud)

调用属性

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;
Run Code Online (Sandbox Code Playgroud)

如果您感兴趣,请参阅用户定义的防护装置,我将其引入是因为这是我需要的少数情况之一。

来自Ultimatecourses的博客:

any当没有其他选择时使用该类型

很难找到好的例子any


Sha*_*gmi 15

I am late to the party but will try to demystify it.

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'
Run Code Online (Sandbox Code Playgroud)

only way to use the method .startsWith() on unknown is explicitly telling compiler the type, like

(canNotBeAnything as string).startsWith('10'); // Chill down TS compiler, I know what I am doing. 
Run Code Online (Sandbox Code Playgroud)

The latter on doesn't show any compilation error but it throws error during runtime because canNotBeAnything is a number type and we are forcing it to be string


Tha*_*aad 6

简单来说,

  • any让你做任何你想做的事
  • unknown如果不先检查类型,则根本不允许您执行任何操作。

例如 -

let a: any;
let b: unknown;

a.anything() // no error
b.anything() // error 'b' is of type 'unknown'.
Run Code Online (Sandbox Code Playgroud)

any禁用 Typescript 所做的所有类型检查。同时unknown迫使您对分配的任何类型都非常严格。


Wil*_*een 5

any 类型:

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

let myVar: any;

myVar[0];
myVar();
myVar.length;
new myVar();
Run Code Online (Sandbox Code Playgroud)

在很多情况下,这对于TS编译器来说太宽容了。即它将允许我们原本会导致运行时错误的操作。

unknown 类型:

unknown类型表示(就像一样any)所有可能的JS值。每个类型都可以分配给type unknown。因此,类型unknown是类型系统(以及any)的另一个通用超类型。然而,TS编译器不会允许在输入值的任何操作unknown。此外,unknown类型只能分配给type 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();
Run Code Online (Sandbox Code Playgroud)


Dmi*_*tin 5

这里的心理很容易any区分unknown

有什么常见的

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

let anyVar: any = 'Value';         // OK
anyVar = 3;                        // OK
Run Code Online (Sandbox Code Playgroud)
let unknownVar: unknown = 'Value'; // OK
unknownVar = 3;                    // OK
Run Code Online (Sandbox Code Playgroud)

查看演示

有什么不同

您可以对 执行任何操作any,但必须执行类型检查或类型断言才能对其进行操作unknown

let anyVar: any = 'Value';

anyVar.length // OK
Run Code Online (Sandbox Code Playgroud)
let unknownVar: unknown = 'Value';

unknownVar.length             // NOT OK

(unknownVar as string).length // OK (with type assertion)
if (typeof unknownVar === 'string') {
  unknownVar.length;          // OK (with type check)
}
Run Code Online (Sandbox Code Playgroud)

查看演示

另请查看帖子“TypeScript 中的未知与任何”(我是帖子作者)。