Skip to main content

类型的类型

JavaScript 有一个 typeof 运算符,它返回一个描述值的字符串。

¥JavaScript has a typeof operator which returns a string describing a value.

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

然而它的局限性在于该字符串仅描述了有关类型的这么多信息。

¥However it is limited in that this string only describes so much about the type.

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

在 Flow 中,有一个类似的 typeof 类型运算符,但它更强大。

¥In Flow, there is a similar typeof type operator, but it's much more powerful.

typeof 类型语法

¥typeof type syntax

typeof 运算符返回要用作类型的给定值的 Flow 类型。

¥The typeof operator returns the Flow type of a given value to be used as a type.

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!

你可以对 typeof 使用任何值,只要参数本身是变量或成员访问:

¥You can use any value with typeof, as long as the arugment itself is a variable or member access:

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!

typeof 继承推断的行为

¥typeof inherits behaviors of inference

当你使用 typeof 时,你将获取 Flow 的推断结果并将其断言为类型。虽然这非常有用,但也可能会导致一些意想不到的结果。

¥When you use typeof, you're taking the results of Flow's inference and asserting it as a type. While this can be very useful, it can also lead to some unexpected results.

例如,当你在 Flow 中使用字面量值时,它们的推断类型是它所属的基元。因此,数字 42 的推断类型为 number。当你使用 typeof 时你可以看到这一点。

¥For example, when you use literal values in Flow, their inferred type is the primitive that it belongs to. Thus, the number 42 has the inferred type of number. You can see this when you use 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 中使用。

¥However, this only happens with the inferred type. If you specify the literal type, it will be used in 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!

typeof 继承其他类型的行为

¥typeof inherits behaviors of other types

Flow 中有许多不同的类型,其中一些类型的行为与其他类型不同。这些差异对于特定类型有意义,但对于其他类型则不然。

¥There are many different types in Flow, some of these types behave differently than others. These differences make sense for that particular type but not for others.

当你使用 typeof 时,你将插入另一种类型及其所有行为。这可能会使 typeof 看起来不一致,但实际上并非如此。

¥When you use typeof, you're inserting another type with all of its behaviors. This can make typeof seem inconsistent where it is not.

例如,如果你将 typeof 与类一起使用,你需要记住类是名义类型的,而不是结构类型的。因此具有相同形状的两个类不被认为是等价的。

¥For example, if you use typeof with a class you need to remember that classes are nominally typed instead of structurally typed. So that two classes with the same exact shape are not considered equivalent.

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!