类型类型
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]