TypeScript 中类型注释 `variable: type` 和类型断言 `expression as type` 的详细区别

Rom*_*eau 8 typescript

即使在他的伟大著作TypeScript Deep Dive 中对类型断言进行了basarat解释:

基本上,如果是 的子类型或的子类型,则从 typeS到的断言T成功。STTS

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

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

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

art*_*tem 11

我想知道类型注释variable: type和类型断言表达式作为类型之间的确切区别是什么

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

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

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

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

const foo3 = { n: '' } as Foo; // KO: "Property 's' is missing..."
Run Code Online (Sandbox Code Playgroud)

这里有两种类型:{n?: number, s: string}{n: string}检查兼容性 - 如果它们中的任何一个可以转换为另一个。无论哪种方式都不能完成:在一种方式中,{n: string}缺少非可选s并且n类型错误(必须是number | undefined);换句话说,(must be ) 的{n?: number, s: string}类型错误。nstring

完整的错误信息是

Type '{ n: string; }' cannot be converted to type 'Foo'.
  Property 's' is missing in type '{ n: string; }'.
Run Code Online (Sandbox Code Playgroud)

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


const foo4 = { n: '' as any } as Foo; // ok
Run Code Online (Sandbox Code Playgroud)

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


const foo5 = { n: 1, x: 2 } as Foo;   // KO: "Property 's' is missing..."
Run Code Online (Sandbox Code Playgroud)

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

Type '{ n: number; x: number; }' cannot be converted to type 'Foo'.
   Property 's' is missing in type '{ n: number; x: number; }'.
Run Code Online (Sandbox Code Playgroud)
const foo6 = { s: '', x: 2 } as Foo;  // ok
Run Code Online (Sandbox Code Playgroud)

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


const foo7 = { s: 1, x: 2 } as Foo;   // KO: "Types of property 's' are incompatible."
Run Code Online (Sandbox Code Playgroud)

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