跳至主要內容

typeof 類型

JavaScript 有 typeof 營運子,用來傳回描述值的字串。

1typeof 1 === 'number'2typeof true === 'boolean'3typeof 'three' === 'string'

不過,它的限制在於這個字串只描述了類型的一部分。

1typeof {foo: true} === 'object'2typeof null === 'object'3typeof [true, false] === 'object'

在 Flow 中,有一個類似的 typeof 類型營運子,但它強大許多。

typeof 類型語法

typeof 運算子會傳回給定值所使用的 Flow 類型作為類型。

1let num1 = 42;2let num2: typeof num1 = 3.14;     // Works!3let num3: typeof num1 = 'world';  // Error!
4 5let bool1 = true;6let bool2: typeof bool1 = false; // Works!7let bool3: typeof bool1 = 42; // Error!
8 9let str1 = 'hello';10let str2: typeof str1 = 'world'; // Works!11let str3: typeof str1 = false; // Error!
3:25-3:31: Cannot assign `'world'` to `num3` because string [1] is incompatible with number [2]. [incompatible-type]
7:27-7:28: Cannot assign `42` to `bool3` because number [1] is incompatible with boolean [2]. [incompatible-type]
11:25-11:29: Cannot assign `false` to `str3` because boolean [1] is incompatible with string [2]. [incompatible-type]

只要參數本身是變數或成員存取,您就可以將任何值與 typeof 搭配使用

1let obj1 = {foo: 1, bar: true, baz: 'three'};2let obj2: typeof obj1 = {foo: 42, bar: false, baz: 'hello'};3let num: typeof obj1.bar = 1;4
5let arr1 = [1, 2, 3];6let arr2: typeof arr1 = [3, 2, 1];7
8type T = typeof {a: 1}; // Invalid!
8:17-8:17: `typeof` can only be used to get the type of variables.

typeof 會繼承推論行為

當您使用 typeof 時,您會採用 Flow 推論的結果並將其斷言為類型。雖然這可能非常有用,但它也可能導致一些意外的結果。

例如,當您在 Flow 中使用文字值時,它們的推論類型屬於它所屬的原語。因此,數字 42 的推論類型為 number。當您使用 typeof 時,您可以看到這一點。

1let num1 = 42;2let num2: typeof num1 = 3.14;    // Works!3
4let bool1 = true;5let bool2: typeof bool1 = false; // Works!6
7let str1 = 'hello';8let str2: typeof str1 = 'world'; // Works!

不過,這只會發生在推論類型中。如果您指定文字類型,它將用於 typeof

1let num1: 42 = 42;2let num2: typeof num1 = 3.14;    // Error!
3 4let bool1: true = true;5let bool2: typeof bool1 = false; // Error!
6 7let str1: 'hello' = 'hello';8let str2: typeof str1 = 'world'; // Error!
2:25-2:28: Cannot assign `3.14` to `num2` because number [1] is incompatible with number literal `42` [2]. [incompatible-type]
5:27-5:31: Cannot assign `false` to `bool2` because boolean [1] is incompatible with boolean literal `true` [2]. [incompatible-type]
8:25-8:31: Cannot assign `'world'` to `str2` because string [1] is incompatible with string literal `hello` [2]. [incompatible-type]

typeof 會繼承其他類型的行為

Flow 中有許多不同的類型,其中一些類型的行為與其他類型不同。這些差異對於特定類型來說是有意義的,但對於其他類型來說則不然。

當您使用 typeof 時,您會插入具有所有行為的另一種類型。這可能會讓 typeof 看起來不一致,但事實並非如此。

例如,如果您對類別使用 typeof,您需要記住類別是名義上類型,而不是結構上類型。因此,具有完全相同形狀的兩個類別不被視為等效。

1class MyClass {2  method(val: number) { /* ... */ }3}4
5class YourClass {6  method(val: number) { /* ... */ }7}8
9let test1: typeof MyClass = YourClass; // Error!
10let test2: typeof MyClass = MyClass; // Works!
9:29-9:37: Cannot assign `YourClass` to `test1` because `YourClass` [1] is incompatible with `MyClass` [2]. [incompatible-type]