類型轉換表達式
有時,在不使用函式或變數的情況下,確認類型會很有用。為此,Flow 支援內嵌類型轉換表達式語法,可用於許多不同的方式。
類型轉換表達式語法
若要建立類型轉換表達式,請使用關鍵字 as
將值轉換為類型
value as Type
這也可以稱為「as 表達式」。
在 Flow 版本 0.229 之前,使用 舊版語法
(value: Type)
。
類型轉換表達式可以出現在任何表達式出現的地方
let val = value as Type;
let obj = {prop: value as Type};
let arr = [value as Type, value as Type] as Array<Type>;
值本身也可以是表達式
12 + 2 as number;
請注意,as
算子具有與 in
和 instanceof
相同的 優先順序。因此,可能需要在表達式周圍加上括號
11 === 1 as boolean; // Error! 2// Above same as `1 === (1 as boolean)3
4(1 === 1) as boolean; // Works!
1:7-1:7: Cannot cast `1` to boolean because number [1] is incompatible with boolean [2]. [incompatible-cast]
此外,在表達式陳述的背景下,可能模稜兩可地解析為陳述的表達式需要括號
1({a: 1}) as {a: number}; // Needs parens to disambiguate from block statement2const x = {a: 1} as {a: number}; // No parens needed, as not in expression statement context
當你剝離類型後,剩下的就是值
value as Type;
轉換為
value;
類型斷言
使用類型轉換表達式,你可以斷言值是特定類型。
1let value = 42;2
3value as 42; // Works!4value as number; // Works!5value as string; // Error!
5:1-5:5: Cannot cast `value` to string because number [1] is incompatible with string [2]. [incompatible-cast]
以這種方式斷言類型,其作用與類型在其他地方的作用相同。
類型轉換
當你撰寫類型轉換表達式時,該表達式的結果是具有提供類型之值。如果你保留結果值,它將具有新的類型。
1let value = 42;2
3value as 42; // Works!4value as number; // Works!5
6let newValue = value as number;7
8newValue as 42; // Error! 9newValue as number; // Works!
8:1-8:8: Cannot cast `newValue` to number literal `42` because number [1] is incompatible with number literal `42` [2]. [incompatible-cast]
不允許不安全的向下轉型
1const fooObj = {foo: 1};2const otherObj = fooObj as {foo: number, bar: string}; // ERROR
2:18-2:23: Cannot cast `fooObj` to object type because property `bar` is missing in object literal [1] but exists in object type [2]. [prop-missing]
採用 as
語法
若要將 as
關鍵字用於類型轉換,你需要升級基礎架構,以便它支援該語法
- Flow 和 Flow Parser:0.229+
- Prettier:3.1+
- Babel:使用 babel-plugin-syntax-hermes-parser 外掛程式版本 0.19+,請參閱我們的 Babel 指南 以取得更多詳細資訊。
- ESLint:使用 hermes-eslint 外掛程式版本 0.19+,請參閱我們的 ESLint 指南 以取得更多詳細資訊。
有關如何移轉至新的轉換語法 (as
) 的更多詳細資訊,請查看我們的 部落格文章。
使用類型轉換表達式
注意:我們將逐步示範如何使用類型轉換表達式。這個範例在實務上並非解決得很好。
透過 any
進行類型轉換
由於類型轉換的作用與所有其他類型註解相同,因此你只能將值轉換為較不具體的類型。你無法變更類型或使其更具體。
但你可以使用 any 轉換成任何你想要的類型。
1let value = 42;2
3value as number; // Works!4value as string; // Error! 5
6let newValue = value as any as string;7
8newValue as number; // Error! 9newValue as string; // Works!
4:1-4:5: Cannot cast `value` to string because number [1] is incompatible with string [2]. [incompatible-cast]8:1-8:8: Cannot cast `newValue` to number because string [1] is incompatible with number [2]. [incompatible-cast]
透過將值轉換成 any
,你就可以轉換成任何你想要的類型。
這是不安全的,也不建議這麼做。但當你使用一個類型很困難或不可能,而且想要確保結果具有所需類型時,這有時會很有用。
例如,以下是用於複製物件的函數。
1function cloneObject(obj: any) {2 const clone: {[string]: mixed} = {};3
4 Object.keys(obj).forEach(key => {5 clone[key] = obj[key];6 });7
8 return clone;9}
為此建立一個類型會很困難,因為我們是根據另一個物件建立一個新的物件。
如果我們透過 any 轉換,我們可以傳回一個更有用的類型。
1function cloneObject<T: {+[key: string]: mixed }>(obj: T): T {2 const clone: {[string]: mixed} = {};3
4 Object.keys(obj).forEach(key => {5 clone[key] = obj[key];6 });7
8 return clone as any as T;9}10
11const clone = cloneObject({12 foo: 1,13 bar: true,14 baz: 'three'15});16
17clone.foo as 1; // Works!18clone.bar as true; // Works!19clone.baz as 'three'; // Works!
舊版轉換語法
在 0.229 版本之前,若要建立一個 value
周圍的類型轉換表達式,你會新增一個冒號 :
和 Type
,並用括號 (
)
包住表達式。
(value: Type)
注意:括號是必要的,以避免與其他語法產生歧義。