【问题标题】:Detailed differences between type annotation `variable: type` and type assertion `expression as type` in TypeScriptTypeScript 中类型注解 `variable: type` 和类型断言 `expression as type` 的详细区别
【发布时间】:2017-12-28 09:15:39
【问题描述】:

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

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

我想知道类型注释 variable: type 和类型断言 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."

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

【问题讨论】:

  • 这很有趣,因为当您为属性提供错误类型时它会出错,但错误消息总是与其他属性有关。除此之外,如果您提供的属性名称是正确的类型,它允许省略或添加其他属性,这似乎是有道理的。

标签: typescript


【解决方案1】:

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

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

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

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

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

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

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

完整的错误信息是

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

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


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

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


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

{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; }'.

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

之所以有效,是因为 {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."

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'.

【讨论】:

    猜你喜欢
    • 2020-08-06
    • 2015-07-17
    • 2018-10-05
    • 2016-01-16
    • 2013-12-02
    • 2021-04-20
    • 2015-09-08
    • 2023-02-18
    • 2016-02-03
    相关资源
    最近更新 更多