在 TypeScript 中,類型轉換主要分為?類型斷言(Type Assertion)、類型守衛(Type Guard)?和?類型兼容轉換?三種方式。以下是詳細分類和示例:
一、類型斷言(Type Assertion)
強制編譯器將值視為特定類型,不改變運行時行為。
1.?尖括號語法
let value: any = "hello";
let length: number = (<string>value).length;
2.?as 語法(更推薦,JSX 中必須使用)
let value: any = "hello";
let length: number = (value as string).length;
3.?非空斷言(Non-null Assertion)
斷言值不為?null
?或?undefined
:
function printLength(str: string | null) {console.log((str!).length); // 斷言 str 不為 null
}
二、類型守衛(Type Guard)
在運行時檢查類型,縮小類型范圍。
1.?typeof 守衛
function add(a: number | string, b: number | string): number {if (typeof a === "number" && typeof b === "number") {return a + b; // a 和 b 被縮小為 number}return Number(a) + Number(b);
}
2.?instanceof 守衛
class Animal { speak() {} }
class Dog extends Animal { bark() {} }function printPet(pet: Animal) {if (pet instanceof Dog) {pet.bark(); // pet 被縮小為 Dog}
}
3.?自定義類型守衛
interface Fish { swim: () => void }
interface Bird { fly: () => void }function isFish(pet: Fish | Bird): pet is Fish {return (pet as Fish).swim !== undefined;
}function move(pet: Fish | Bird) {if (isFish(pet)) {pet.swim(); // 類型為 Fish} else {pet.fly(); // 類型為 Bird}
}
三、類型兼容轉換
基于類型結構的隱式轉換(無需斷言)。
1.?子類型賦值給父類型
interface Animal { name: string }
interface Dog extends Animal { breed: string }let dog: Dog = { name: "Buddy", breed: "Labrador" };
let animal: Animal = dog; // 合法:Dog 是 Animal 的子類型
2.?聯合類型轉換
let value: string | number = "hello";
let str: string = value as string; // 斷言為 string
四、類型轉換工具類型
1.?typeof
獲取值的類型:
const person = { name: "Alice", age: 30 };
type PersonType = typeof person; // { name: string; age: number }
2.?keyof
獲取類型的所有屬性名:
type PersonKeys = keyof typeof person; // "name" | "age"
3.?類型映射
type ReadonlyPerson = Readonly<typeof person>; // 所有屬性變為只讀
五、運行時類型轉換
實際修改值的類型(與 TypeScript 類型系統無關)。
1.?轉字符串
String(123); // "123"
JSON.stringify({}); // "{}"
2.?轉數字
Number("42"); // 42
parseInt("10px"); // 10
+"5"; // 5(一元加號)
3.?轉布爾值
Boolean(0); // false
!!null; // false(雙重否定)
六、常見陷阱與最佳實踐
-
過度使用斷言
- 避免使用?
as any
?繞過類型檢查,優先使用類型守衛。
- 避免使用?
-
類型守衛與斷言的區別
- 類型守衛:運行時檢查,真正縮小類型范圍。
- 類型斷言:僅告知編譯器類型,不驗證值的實際類型。
-
使用類型謂詞(Type Predicate)
function isString(value: any): value is string {return typeof value === "string"; }
總結
場景 | 方法 | 示例 |
---|---|---|
強制類型轉換(編譯時) | 類型斷言(as 或 <>) | (value as string).length |
運行時類型檢查 | 類型守衛(typeof/instanceof) | if (typeof x === 'number') { ... } |
獲取已有類型 | typeof | type T = typeof obj |
轉換值的實際類型 | String()/Number()/Boolean() | Number("42") |
泛型約束 | extends | function identity<T extends string>(x: T) |
合理使用這些工具,可以讓你的 TypeScript 代碼既安全又靈活。