TypeScript 允许你覆盖它的推断,并且能以你任何你想要的方式分析它,这种机制被称为「类型断言」。类型断言使用as
关键字或者<type>
表示。
const foo = {};
foo.bar = 123; // Error: 'bar' 属性不存在于 ‘{}’
foo.bas = 'hello'; // Error: 'bas' 属性不存在于 '{}'
由于对象foo不存在任何属性,因此给属性赋值就报错了,可以通过类型断言避免此问题。
interface Foo {
bar: number;
bas: string;
}
const foo = {} as Foo;
foo.bar = 123;
foo.bas = 'hello';
// 另一种形式(由于这种形式和jsx容易混淆,建议使用as关键字)
const bar = <Foo>{};
类型断言应该少用
使用类型断言,如果我们没有按接口约定添加属性,ts不会发出错误警告。
interface Foo {
bar: number;
bas: string;
}
// 没有为foo添加bar和bas属性,也没有错误警告
const foo = {} as Foo
// 没有为bar添加bar和bas属性,也没有错误警告
const bar = <Foo>{}
为了避免出现上面的问题,建议使用ts自身提供的类型推断,减少使用类型断言。
const foo: Foo = {
}
使用示例
function handler(event: Event) {
// 可以使用MouseEvent的属性和方法
const mouseEvent = event as MouseEvent;
}
说明:MouseEvent 派生自 UIEvent,UIEvent 派生自 Event
,因此MouseEvent继承了UIEvent和Event的属性和方法。但不能把event断言成HTMLElement
,因为Event和HTMLElement没有任何关系。
function handler(event: Event) {
const element = event as HTMLElement; // Error: 'Event' 和 'HTMLElement' 中的任何一个都不能赋值给另外一个
}
如果非要断言成HTMLElement也是有办法的,使用双重断言。首先断言成兼容所有类型的 any,再断言成HTMLElement。
function handler(event: Event) {
const element = (event as any) as HTMLElement; // ok
}
判断是否能够断言
当 S 类型是 T 类型的子集,或者 T 类型是 S 类型的子集时,S 能被成功断言成 T,当然T 能被成功断言成 S。这是为了在进行类型断言时提供额外的安全性,完全毫无根据的断言是危险的,如果你想这么做,你可以使用 any
关于继承和派生
假设有基类A,子类B、派生类C,那么B类继承了A的属性和方法,同时可以定义自己的属性和方法。C类是派生类,他实现了A的接口,同时也可以定于你自己的属性和方法。