TypeScript 允许重写已经被推断和分析的类型,通过“类型断言”机制区实现。
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript会假设你,程序员,已经进行了必须的检查。

1.类型断言的常见方式

ts 中的类型断言主要有以下两种语法

1.1 as 语法
interface Foo{
bar:number,
baz:string
}

const foo ={} as Foo;
foo.bar = 123;
foo.baz = 'hello';
1.2 尖括号语法 < xxx >
interface Foo{
bar:number,
baz:string
}

const foo =<Foo>{};
foo.bar = 123;
foo.baz = 'hello';

这两种语法是等价的,但是TypeScript里使用JSX时,只有 as语法断言是被允许的。主要是因为jsx 是js 和 xml 混合的语法,使用< xxx >会存在歧义。建议使用 as 语法。

2.类型断言的缺点

类型断言能够方便开放人员将遗留项目改造为ts 项目,比如能做到直接复制 js 代码到 ts 中,几乎没有修改,而类型断言的缺点也正是这一点。类型断言屏蔽了编译器对代码的检查,因为类型断言告诉 编译器 类型是可信的, 无效检查,从而导致ts 编译器不会对此发出错误警告。

因此建议使用强类型校验,而非类型断言

interface Foo{
bar:number,
baz:string
}

const foo: Foo = {
	// 编译器会有相应提示
    bar :123,
    baz: 'hello'
};

3.双重断言

下面的示例可以正常运行,是因为MouseEvent 是 Event 的子类

function handle(event: Event) {
    const mouseEvent = event as MouseEvent;
}

而下面的代码会报错,因为HTMLElement 不是 Event 的子类

function handle(event: Event) {
    const element = event as HTMLElement; // 报错
}

如果想要去除报错,可以使用双层断言

function handle(event: Event) {
    const element = (event as any) as HTMLElement; // 双层
}

总结双重断言:

  • 1.双重断言基于两个前提:
  • (1) 子类型可以被断言为父类型
  • (2) any 这种类型可以被赋值给几乎其他任何类型(never 等除外)
  • 2.双重断言断言可以实现 子类型转换为另外一种子类型( 子类型->父类型->子类型)
  • 3.尽量不使用双重断言,双重断言会破坏原有类型关系