跳至主要內容

類型轉換表達式

有時,在不使用函式或變數的情況下,確認類型會很有用。為此,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 算子具有與 ininstanceof 相同的 優先順序。因此,可能需要在表達式周圍加上括號

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 關鍵字用於類型轉換,你需要升級基礎架構,以便它支援該語法

有關如何移轉至新的轉換語法 (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)

注意:括號是必要的,以避免與其他語法產生歧義。