TypeScript 中类型注释 `variable: type` 和类型断言 `expression as type` 的详细区别 [英] Detailed differences between type annotation `variable: type` and type assertion `expression as type` in TypeScript

查看:33
本文介绍了TypeScript 中类型注释 `variable: type` 和类型断言 `expression as type` 的详细区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使使用 basarat 在他的好书 TypeScript 深入研究:

Even with basarat explanations on type assertions in his great book TypeScript Deep Dive:

基本上,如果 ST 的子类型,则从 S 类型到 T 的断言成功TS 的子类型.

Basically, the assertion from type S to T succeeds if either S is a subtype of T or T is a subtype of S.

我想知道类型注释 variable: type 和类型断言 expression as type 之间的确切区别是什么,更准确地说,当类型断言是否有效时,尤其是关于TypeScript 错误有时令人惊讶:请参阅下面的 foo3foo5 变量:

I was wondering what is the exact difference between type annotation variable: type and type assertion expression as type, more precisely when type assertion is working or not, especially regarding that TypeScript errors are sometime surprising: see them for the foo3 and foo5 variables bellow:

interface Foo {
    n?: number;
    s: string;
}

const foo1 = {} as Foo;               // ok
const foo2 = { n: 1 } as Foo;         // ok
const foo3 = { n: '' } as Foo;        // KO: "Property 's' is missing..."
const foo4 = { n: '' as any } as Foo; // ok
const foo5 = { n: 1, x: 2 } as Foo;   // KO: "Property 's' is missing..."
const foo6 = { s: '', x: 2 } as Foo;  // ok
const foo7 = { s: 1, x: 2 } as Foo;   // KO: "Types of property 's' are incompatible."

我注意到的其他区别:在 VSCode 的 Foo 接口中重命名 n 属性不会传播到被断言的表达式,而它正在处理类型注释的变量.

Other difference I've noticed: renaming the n property in the Foo interface in VSCode does not propagate to expressions being asserted, while it's working with type annotated variables.

推荐答案

我想知道类型注释之间的确切区别是什么variable: type 和 type assertion expression as type

I was wondering what is the exact difference between type annotation variable: type and type assertion expression as type

类型声明 variable: type 告诉编译器变量必须始终符合声明的类型.当一个值被赋值给变量时(该值必须与声明的类型兼容),以及每当使用该变量时(变量的声明类型必须与变量的使用方式兼容),类型检查器使用它每个特定的地方).

Type declaration variable: type tells the compiler that the variable must always conform to the declared type. It is used by typechecker when a value is assigned to the variable (the value must be compatible with the declared type), and also whenever the variable is used (the declared type of the variable must be compatible with whatever way the variable is used in each particular place).

类型断言会覆盖内置的类型兼容性规则.它允许您告诉编译器您知道该值实际上符合您在断言中提供的类型,从而抑制有关类型不兼容的错误消息.但是,有一些限制 - 您不能仅仅断言变量具有您想要的任何类型(顺便说一句,any 类型就是为此).正如您在问题中引用的那样,要使类型断言起作用,

Type assertion overrides built-in type compatibility rules. It allows you to tell the compiler that you know that the value actually conforms to the type you give in the assertion, thus suppressing error message about type incompatibility. There are limits, however - you can't just assert that variable has any type you want (BTW there is any type just for that). As you quoted in the question, for type assertion to work,

如果 S 是 T 的子类型或 T 是 S 的子类型,则从类型 S 到 T 的断言成功

the assertion from type S to T succeeds if either S is a subtype of T or T is a subtype of S

它在每个示例中都以这种方式工作:

It works exactly in that way in each example:

const foo3 = { n: '' } as Foo; // KO: "Property 's' is missing..."

这里检查了两种类型:{n?: number, s: string}{n: string} 的兼容性 - 如果它们中的任何一个可以转换为其他.无论哪种方式都无法做到:在一种方式中, {n: string} 缺少非可选的 s 并且 n 有错误类型(必须是 number | undefined);换句话说,{n?: number, s: string}n 类型错误(必须是 string).

Here two types: {n?: number, s: string} and {n: string} are checked for compatibility - if any of them can be converted to another. It can't be done either way: in one way, {n: string} is missing non-optional s and n has the wrong type (must be number | undefined); in another way, {n?: number, s: string} has wrong type for n (must be string).

完整的错误信息是

Type '{ n: string; }' cannot be converted to type 'Foo'.
  Property 's' is missing in type '{ n: string; }'.

在报告结构类型不兼容时,编译器仅选择一个不兼容属性显示在错误消息中 - 它可能是上述三种不兼容中的任何一种.

When reporting structural type incompatibility, the compiler chooses just one incompatible property to show in the error message - it could be any of the three incompatibilities mentioned above.

const foo4 = { n: '' as any } as Foo; // ok

之所以有效,是因为 {n?: number, s: string}{n: any} 兼容:第一个可以分配给第二个 - any 与任何东西兼容,而 s 只是被忽略(基本上,如果一个值具有与声明类型兼容的所有非可选属性,则它与类型兼容)

Works because {n?: number, s: string} is compatible with {n: any}: the first one can be assigned to the second - any is compatible with anything, and s is just ignored (basically, a value is compatible with the type if it has all non-optional properties compatible with declared type)

const foo5 = { n: 1, x: 2 } as Foo;   // KO: "Property 's' is missing..."

{n: number, x: number} 不可分配给 {n?: number, s: string} -s 是缺少,正如编译器所说:

{n: number, x: number} is not assignable to {n?: number, s: string} -s is missing, as compiler says:

Type '{ n: number; x: number; }' cannot be converted to type 'Foo'.
   Property 's' is missing in type '{ n: number; x: number; }'.

<小时>

const foo6 = { s: '', x: 2 } as Foo;  // ok

之所以有效,是因为 {s: string, x: number} 可分配给 {n?: number, s: string}: s没问题,缺少 n 没问题,因为它被声明为可选,额外的 x 被忽略

Works because {s: string, x: number} is assignable to {n?: number, s: string}: s is OK, missing n is OK because it's declared as optional, extra x is ignored

const foo7 = { s: 1, x: 2 } as Foo;   // KO: "Types of property 's' are incompatible."

s 的类型不兼容:

Type '{ s: number; x: number; }' cannot be converted to type 'Foo'.
  Types of property 's' are incompatible.
    Type 'number' is not comparable to type 'string'.

这篇关于TypeScript 中类型注释 `variable: type` 和类型断言 `expression as type` 的详细区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆