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
を使用する場合、クラスは*構造的*型付けではなく*公称的*型付けであることを覚えておく必要があります。そのため、まったく同じ形状を持つ2つのクラスは同等とは見なされません。
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]