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的接口,同時也可以定於你自己的屬性和方法。