工具类型
Flow 提供了一组工具类型来操作其他类型以创建新类型。
¥Flow provides a set of utility types to operate on other types to create new types.
$Keys<T>
你可以从 对象类型 中提取密钥的类型。通常,这将是 字符串字面量 类型中的 联合:
¥You can extract the type of the keys from an object type. Typically this will be a union of string literal types:
1const countries = {2 US: "United States",3 IT: "Italy",4 FR: "France"5};6
7type Country = $Keys<typeof countries>;8
9const italy: Country = 'IT'; // Works10const nope: Country = 'nope'; // Error!
在上面的示例中,Country
的类型相当于 type Country = 'US' | 'IT' | 'FR'
,但 Flow 能够从 countries
的键中提取它。
¥In the example above, the type of Country
is equivalent to type Country = 'US' | 'IT' | 'FR'
, but Flow was able to extract it from the keys of countries
.
如果你想创建枚举类型,Flow 枚举 可能更适合你的用例。
¥If you want to create an enum type, Flow Enums might be a better fit for your use-case.
$Values<T>
$Values<T>
表示 对象类型 中可枚举属性的所有值类型的联合类型,或元素的联合类型 数组 或 元组 类型(支持 Flow 版本中的数组和元组
¥$Values<T>
represents the union type of all the value types of the enumerable properties in an object type,
or the elements of an array or tuple type (support for arrays and tuples in Flow version
):
1type Props = {2 name: string,3 age: number,4};5
6// The following two types are equivalent:7type PropValues = string | number;8type Prop$Values = $Values<Props>;9
10const name: Prop$Values = 'Jon'; // Works11const age: Prop$Values = 42; // Works12const fn: Prop$Values = true; // Error!
对于数组和元组:
¥For arrays and tuples:
1type Arr = Array<string>;2type Str = $Values<Arr>; //=> string3's' as Str; // OK4
5type Tup = [1, 2];6type Num = $Values<Tup>; //=> 1 | 271 as Num; // OK
请注意,在 typeof
对象或数组字面量上使用 $Values
将导致类型比你预期的更通用:
¥Note that using $Values
on the typeof
an object or array literal will result in a type more general than you might expect:
1const obj = {2 foo: 1,3 bar: 2,4};5
6function acceptsValues(x: $Values<typeof obj>) { /* ... */ }7
8acceptsValues(1); // Works9acceptsValues(3); // Works, because the type was interpreted as `number`.
如果你在对象字面量表达式上使用 Object.freeze
,则此行为会发生变化:
¥This behavior changes if you use Object.freeze
on the object literal expression:
1const obj = Object.freeze({2 foo: 1,3 bar: 2,4});5
6function acceptsValues(x: $Values<typeof obj>) { /* ... */ }7
8acceptsValues(1); // Works9acceptsValues(3); // Error! Because the type was interpreted as `1 | 2`.
如果你想创建枚举类型,Flow 枚举 可能更适合你的用例。
¥If you want to create an enum type, Flow Enums might be a better fit for your use-case.
$ReadOnly<T>
$ReadOnly<T>
是一种类型,表示给定 对象类型 或 元组类型 T
的只读版本(对元组的支持适用于 Flow
¥$ReadOnly<T>
is a type that represents the read-only version of a given object type
or tuple type T
(support for tuples is for Flow
)。 只读对象类型是键全部为 只读 的对象类型。类似地,只读元组是每个元素都是 只读 的元组。
¥). A read-only object type is an object type whose keys are all read-only. Similarly, a read-only tuple is one where each element is read-only.
这意味着以下内容是等效的:
¥This means that the following are equivalent:
1type ReadOnlyObj = {2 +key: number, // read-only field, marked by the `+` annotation3};4type ReadOnlyTuple = [+foo: number];
→
1type ReadOnlyObj = $ReadOnly<{2 key: number,3}>;4type ReadOnlyTuple = $ReadOnly<[number]>;
当你需要使用已定义的对象类型的只读版本,而无需手动重新定义每个键并将其注释为只读时,这非常有用。例如:
¥This is useful when you need to use a read-only version of an object type you've already defined, without manually having to re-define and annotate each key as read-only. For example:
1type Props = {2 name: string,3 age: number,4};5
6type ReadOnlyProps = $ReadOnly<Props>;7
8function render(props: ReadOnlyProps) {9 const {name, age} = props; // Works10 props.age = 42; // Error!11}
此外,其他工具类型(例如 spread)可能会删除任何读/写注释,因此 $ReadOnly<T>
是一种在对其进行操作后快速使对象再次变为只读的便捷方法:
¥Additionally, other utility types, such as spread, may strip any read/write annotations, so $ReadOnly<T>
is a handy way to quickly make the object read-only again after operating on it:
1type Obj = {2 +key: number,3};4
5type MappedObj = $ReadOnly<{...Obj, foo: string}> // Still read-only
$ReadOnly
实用程序适用于对象和元组类型。如果要将其他类型设置为只读,可以使用以下其中一种:
¥The $ReadOnly
utility works on object and tuple types.
If you want to make other types read-only, you can use one of the following:
Array<T>
->$ReadOnlyArray<T>
Set<T>
->$ReadOnlySet<T>
Map<K, V>
->$ReadOnlyMap<K, V>
WeakSet<T>
->$ReadOnlyWeakSet<T>
WeakMap<K, V>
->$ReadOnlyWeakMap<K, V>
Partial<T>
≥0.201{#toc-partial}
该实用程序将对象或接口的所有命名字段转换为可选字段,同时保留对象的所有其他属性(例如精确性、方差)。使用此实用程序代替 $Shape
。
¥This utility converts all of an object or interface's named fields to be optional,
while maintaining all the object's other properties (e.g. exactness, variance).
Use this utility instead of $Shape
.
自流
¥Since Flow
≥0.212,它还将元组类型的所有元素转换为 optional。
¥, it also converts all of a tuple type's elements to be optional.
对象示例:
¥Example for objects:
1type Person = {2 name: string,3 age: number,4};5type PartialPerson = Partial<Person>;6// Above equivalent to `{name?: string, age?: number}`7
8const a: PartialPerson = {}; // OK9const b: PartialPerson = {name: 'George'}; // OK10const c: PartialPerson = {name: 'George', age: 123}; // OK11
12c as Person; // ERROR: `PersonDetails` is not a `Person` (unlike with `$Shape`)
对于元组:
¥For tuples:
1type AllRequired = [number, string];2[] as Partial<AllRequired>; // OK: like `[a?: number, b?: string]` now
由于可变性,无法将 T
类型的对象或元组提供给 Partial<T>
。你可以通过将对象设置为 只读 来解决此问题:
¥A object or tuple of type T
cannot be supplied to Partial<T>
, due to mutability. You can resolve this by making the object read-only:
1type Person = {2 name: string,3 age: number,4};5
6const person: Person = {name: 'George', age: 123};7
8function noPerson(o: Partial<Person>) {9 // Can mutate:10 o.name = undefined;11}12noPerson(person); // Error!13
14function okPerson(o: $ReadOnly<Partial<Person>>) {15 // Can't mutate - it's read-only!16}17okPerson(person); // Works
注意:在 Flow 版本 0.201 之前,此工具类型被命名为 $Partial
。
¥Note: Up until Flow version 0.201, this utility type was named $Partial
.
Required<T>
≥0.201{#toc-required}
Required
工具类型与 Partial
相反:它将对象或接口的所有可选字段转换为必需字段。
¥The Required
utility type is the opposite of Partial
:
it converts all of an object or interface’s optional fields to be required.
自流
¥Since Flow
≥0.212,它还将元组类型的所有元素转换为 required。
¥, it also converts all of a tuple type's elements to be required.
对象示例:
¥Example for objects:
1type PartialPerson = {2 name?: string,3 age?: number,4};5type Person = Required<PartialPerson>;6// Above equivalent to `{name: string, age: number}`7
8const a: Person = {name: 'George', age: 123}; // OK9const b: Person = {age: 123}; // ERROR: missing `name` property
对于元组:
¥For tuples:
1type AllOptional = [a?: number, b?: string];2[] as Required<AllOptional>; // ERROR: like `[a: number, b: string]` now
ReturnType<F>
≥0.209{#toc-return-type}
此工具类型从给定函数类型中提取返回类型。
¥This utility type extracts the return type from a given function type.
1declare function f(s: string, n: number): boolean;2type Bool = ReturnType<typeof f>;3true as Bool;41 as Bool; // Error: number is not boolean
Parameters<F>
≥0.209{#toc-parameters}
该工具类型将给定函数类型中的参数类型提取到 元组类型。
¥This utility type extracts the parameter types from a given function type into a tuple type.
1declare function f(s: string, n: number): boolean;2type Tuple = Parameters<typeof f>; // Evaluates to [string, number]3's' as Tuple[0];41 as Tuple[1];5false as Tuple[2]; // Error: tuple type only has two elements
Exclude<T, U>
≥0.209{#toc-exclude}
此工具类型从 T
中排除 U
的所有子类型。
¥This utility type excludes all subtypes of U
from T
.
1type T = Exclude<1 | 2 | 3 | 4, 1 | 3>; // evaluates to 2 | 421 as T; // error32 as T; // ok43 as T; // error54 as T; // ok
Extract<T, U>
≥0.209{#toc-extract}
此工具类型仅保留 T
中的 U
子类型。
¥This utility type retains only subtypes of U
from T
.
1declare class Car {}2declare class Animal {}3declare class Dog extends Animal {}4declare class Cat extends Animal {}5type T = Extract<Car | Dog | Cat, Animal>; // evaluates to Dog | Cat6new Car() as T; // error7new Dog() as T; // ok8new Cat() as T; // ok
ThisParameterType<F>
≥0.209{#toc-this-parameter-type}
此工具类型提取给定函数类型的 this
参数的类型。
¥This utility type extracts the type of the this
parameter of a given function type.
1type T = ThisParameterType<(this: number, bar: string) => void>; // Evaluates to number2'1' as T; // error32 as T; // ok
OmitThisParameter<F>
≥0.209{#toc-omit-this-parameter-type}
此工具类型从给定函数类型中删除 this
参数。
¥This utility type removes the this
parameter from a given function type.
1type HasThisParamFun = (this: number, bar: string) => void;2type NoThisParamFun = OmitThisParameter<HasThisParamFun> // Evaluates to (bar: string) => void3declare const hasThisParam: HasThisParamFun;4declare const noThisParam: NoThisParamFun;5
6hasThisParam(''); // error: global object is not number7noThisParam(''); // ok: no this type requirement
Pick<O, Keys>
≥0.211{#toc-pick}
此工具类型允许你使用另一个对象类型的字段子集生成对象类型。
¥This utility type allows you to generate an object type using a subset of the fields from another object type.
1type O = {foo: number, bar: string, baz: boolean};2type FooAndBar = Pick<O, 'foo' | 'bar'>;3
4declare const fooAndBar: FooAndBar;5fooAndBar.baz; // error: baz is missing6fooAndBar.foo as number; // ok7fooAndBar.bar as string; // ok
Omit<O, Keys>
≥0.211{#toc-omit}
此工具类型允许你通过省略另一个对象类型中的指定字段来生成对象类型。
¥This utility type allows you to generate an object type by omitting the specified fields from another object type.
1type O = {foo: number, bar: string, baz: boolean};2type JustBaz= Omit<O, 'foo' | 'bar'>;3
4declare const justBaz: JustBaz;5justBaz.baz as boolean; // ok6justBaz.foo; // error: missing foo7justBaz.bar; // error: missing bar
Record<Keys, Type>
≥0.211{#toc-record}
此工具类型允许你根据每个字段具有给定 Type
的键并集生成对象类型。
¥This utility type allows you to generate an object type from a union of keys with the given
Type
for each field.
1type NumberRecord = Record<'foo' | 'bar', number>;2declare const numberRecord: NumberRecord;3numberRecord.foo as number; // ok4numberRecord.bar as number; // ok5numberRecord.baz; // error
请注意,Record
与使用索引器不同:
¥Note that Record
is different than using an indexer:
1type NumberRecord = Record<'foo' | 'bar', number>;2type IndexedObject = {['foo' | 'bar']: number};3
4// Record uses explicit fields, which means they are all required5const rec: NumberRecord = {}; // error6// Indexers do not have this same requirement7const idx: IndexedObject = {}; // no error
$Exact<T>
你可以使用 $Exact
使 不精确的对象类型 精确:
¥You can use $Exact
to make an inexact object type exact:
1type InexactUser = {name: string, ...};2type ExactUser = $Exact<InexactUser>;3
4const user = {name: 'John Wilkes Booth'};5// These will both be satisfied because they are equivalent:6const a: ExactUser = user;7const b: {name: string} = user;
这是一种要避免的工具类型,因为从精确的对象类型开始并使用 对象类型传播 使其变得不精确(如果你希望同时拥有一个对象类型的不精确和精确变体)会更清晰、更简洁:
¥This is an utility type to avoid, as it's clearer and more concinse to start off with an exact object type and make it inexact using object type spread (if you wish to have both inexact and exact variants of one object type):
1type ExactUser = {name: string};2type InexactUser = {...ExactUser, ...};3
4const user = {name: 'John Wilkes Booth'};5const a: ExactUser = user;
$Diff<A, B>
顾名思义,$Diff<A, B>
是表示 A
和 B
的集合差值的类型,即 A \ B
,其中 A
和 B
都是 对象类型。这是一个例子:
¥As the name hints, $Diff<A, B>
is the type representing the set difference of A
and B
, i.e. A \ B
, where A
and B
are both object types. Here's an example:
1type Props = {name: string, age: number, ...};2type DefaultProps = {age: number};3type RequiredProps = $Diff<Props, DefaultProps>;4
5function setProps(props: RequiredProps) {6 // ...7}8
9setProps({name: 'foo'}); // Works10setProps({name: 'foo', age: 42, baz: false}); // Works, you can pass extra props too11setProps({age: 42}); // Error! `name` is required
你可能已经注意到,该示例不是随机的。$Diff
正是 React 定义文件用来定义 React 组件接受的 props 类型的内容。
¥As you may have noticed, the example is not a random one.
$Diff
is exactly what the React definition file uses to define the type of the props accepted by a React Component.
请注意,如果要从中删除属性的对象没有要删除的属性,即如果 B
具有 A
中不存在的键,则 $Diff<A, B>
将出错:
¥Note that $Diff<A, B>
will error if the object you are removing properties from does not have the property being removed, i.e. if B
has a key that doesn't exist in A
:
1type Props = {name: string, age: number};2type DefaultProps = {age: number, other: string};3type RequiredProps = $Diff<Props, DefaultProps>; // Error!4
5function setProps(props: RequiredProps) {6 props.name;7 // ...8}
作为解决方法,你可以将 A
中不存在的属性指定为可选。例如:
¥As a workaround, you can specify the property not present in A
as optional. For example:
1type A = $Diff<{}, {nope: number}>; // Error!2type B = $Diff<{}, {nope: number | void}>; // Works3
4const a: A = {};5const b: B = {};
$Rest<A, B>
$Rest<A, B>
是表示运行时对象剩余操作的类型,例如:const {foo, ...rest} = obj
,其中 A
和 B
都是 对象类型。此操作的结果类型将是一个对象类型,其中包含 A
自己的属性,但这些属性不是 B
中自己的属性。在 Flow 中,我们将 确切的对象类型 上的所有属性视为 自有的。对于不精确的对象,属性可能是也可能不是。
¥$Rest<A, B>
is the type that represents the runtime object rest operation, e.g.: const {foo, ...rest} = obj
, where A
and B
are both object types.
The resulting type from this operation will be an object type containing A
's own properties that are not own properties in B
.
In flow, we treat all properties on exact object types as own.
For inexact objects, a property may or may not be own.
例如:
¥For example:
1type Props = {name: string, age: number};2
3const props: Props = {name: 'Jon', age: 42};4const {age, ...otherProps} = props;5otherProps as $Rest<Props, {age: number}>;6otherProps.age; // Error!
与 $Diff<A, B>
的主要区别在于 $Rest<A, B>
旨在表示真正的运行时剩余操作,这意味着在 $Rest<A, B>
中对确切的对象类型进行不同的处理。例如,$Rest<{n: number}, {...}>
将导致 {n?: number}
,因为不精确的空对象可能具有 n
属性,而 $Diff<{n: number}, {...}>
将导致 {n: number}
。
¥The main difference with $Diff<A, B>
, is that $Rest<A, B>
aims to represent the true runtime rest operation,
which implies that exact object types are treated differently in $Rest<A, B>
.
For example, $Rest<{n: number}, {...}>
will result in {n?: number}
because an in-exact empty object may have an n
property,
while $Diff<{n: number}, {...}>
will result in {n: number}
.
$NonMaybeType<T>
$NonMaybeType<T>
将类型 T
转换为非 也许输入。换句话说,$NonMaybeType<T>
的值是除了 null
和 undefined
之外的 T
的值。
¥$NonMaybeType<T>
converts a type T
to a non-maybe type.
In other words, the values of $NonMaybeType<T>
are the values of T
except for null
and undefined
.
1type MaybeName = ?string;2type Name = $NonMaybeType<MaybeName>;3
4'Gabriel' as MaybeName; // Works5null as MaybeName; // Works6'Gabriel' as Name; // Works7null as Name; // Error! `null` can't be annotated as Name because Name is not a maybe type
$KeyMirror<O>
$KeyMirror<Obj>
是 $ObjMapi<Obj, F>
的特例,当 F
是恒等函数类型时,即。<K>(K) => K
。换句话说,它将对象的每个属性映射到属性键的类型。你可以写 $KeyMirror<Obj>
,而不是写 $ObjMapi<Obj, <K>(K) => K>
。例如:
¥$KeyMirror<Obj>
is a special case of $ObjMapi<Obj, F>
, when F
is the identity
function type, ie. <K>(K) => K
. In other words, it maps each property of an object
to the type of the property key. Instead of writing $ObjMapi<Obj, <K>(K) => K>
,
you can write $KeyMirror<Obj>
. For example:
1const obj = {2 a: true,3 b: 'foo'4};5
6declare function run<O: {...}>(o: O): $KeyMirror<O>;7
8// newObj is of type {a: 'a', b: 'b'}9const newObj = run(obj);10
11newObj.a as 'a'; // Works12newObj.b as 'a'; // Error! String 'b' is incompatible with 'a'
提示:优先使用 $KeyMirror
而不是 $ObjMapi
(如果可能)来修复某些类型的 [invalid-exported-annotation]
错误。
¥Tip: Prefer using $KeyMirror
instead of $ObjMapi
(if possible) to fix certain
kinds of [invalid-exported-annotation]
errors.
Class<T>
给定类型 T
表示类 C
的实例,类型 Class<T>
是类 C
的类型。例如:
¥Given a type T
representing instances of a class C
, the type Class<T>
is the type of the class C
.
For example:
1class Store {}2class ExtendedStore extends Store {}3class Model {}4
5function makeStore(storeClass: Class<Store>) {6 return new storeClass();7}8
9makeStore(Store) as Store;10makeStore(ExtendedStore) as Store;11makeStore(Model) as Model; // Error!
对于采用类型参数的类,你还必须提供参数。例如:
¥For classes that take type parameters, you must also provide the parameter. For example:
1class ParamStore<T> {2 constructor(data: T) {}3}4
5function makeParamStore<T>(storeClass: Class<ParamStore<T>>, data: T): ParamStore<T> {6 return new storeClass(data);7}8makeParamStore(ParamStore, 1) as ParamStore<number>;9makeParamStore(ParamStore, 1) as ParamStore<boolean>; // Error!
$Exports<T>
以下内容在功能上是等效的
¥The following are functionally equivalent
import typeof * as T from 'my-module';
type T = $Exports<'my-module'>;
$Exports
语法的优点是你可以在同一行上 export
类型
¥The advantage of the $Exports
syntax is that you can export
the type on the same line
export type T = $Exports<'my-module'>;
否则你需要在 import typeof
情况下导出别名
¥where as you would otherwise need to export an alias in the import typeof
case
import typeof * as T from 'my-module';
export type MyModuleType = T;
StringPrefix
和 StringSuffix
¥StringPrefix
and StringSuffix
StringPrefix
和 StringSuffix
类型分别表示具有指定前缀或后缀的字符串。它们的第一个类型参数必须是字符串字面量类型,表示前缀或后缀。
¥The StringPrefix
and StringSuffix
types represent strings with the specified prefix or suffix, respectively.
Their first type argument must be a string literal type, representing the prefix or suffix.
你可以使用 StringPrefix
定义一种接受以 data-
开头的字符串的类型:
¥You could use StringPrefix
to define a type that accepts strings which start with data-
:
1type DataProp = StringPrefix<'data-'>;2'data-foo' as DataProp; // OK3'data-bar' as DataProp; // OK4'random string' as DataProp; // ERROR
你可以使用 StringSuffix
定义一种接受以 !
结尾的字符串的类型:
¥You could use StringSuffix
to define a type that accepts strings which end with !
:
1type Exclaim = StringSuffix<'!'>;2'yay!' as Exclaim; // OK3'woo!' as Exclaim; // OK4'random string' as Exclaim; // ERROR
你可以将它们与 交集类型 结合使用:
¥You can combine these with intersection types:
1type CSSVar = StringPrefix<'var(--'> & StringSuffix<')'>;2'var(--color)' as CSSVar; // OK3'random string' as CSSVar; // ERROR
这两个实用程序都接受可选的第二个类型参数,即余数的类型:
¥Both utilities accept an optional second type argument, which is the type of the remainder:
1type Price = StringPrefix<'$', '1' | '2'>;2'$1' as Price; // OK3'$2' as Price; // OK4'$999' as Price; // ERROR
未指定时,余数的类型仅为 string
。
¥When not specified, the type of the remainder is just string
.
已弃用的工具类型
¥Deprecated utility types
$PropertyType<T, k>
警告:$PropertyType
从 Flow 版本 0.155 开始已弃用,并将在 Flow 的未来版本中删除。
¥WARNING: $PropertyType
is deprecated as of Flow version 0.155, and will be removed in a future version of Flow.
$PropertyType<T, 'k'>
相当于 T['k']
索引访问类型。
¥$PropertyType<T, 'k'>
is equivalent to the T['k']
indexed access type.
$ElementType<T, K>
警告:$ElementType
从 Flow 版本 0.155 开始已弃用,并将在 Flow 的未来版本中删除。
¥WARNING: $ElementType
is deprecated as of Flow version 0.155, and will be removed in a future version of Flow.
$ElementType<T, K>
相当于 T[K]
索引访问类型。
¥$ElementType<T, K>
is equivalent to the T[K]
indexed access type.
即将删除的工具类型
¥To-be-removed utility types
$TupleMap<T, F>
$TupleMap<T, F>
采用可迭代类型 T
(例如:Tuple
或 Array
)和 函数类型 F
,并返回通过将可迭代中每个值的类型与提供的函数类型 F
进行映射而获得的可迭代类型。这类似于 JavaScript 函数 map
。
¥$TupleMap<T, F>
takes an iterable type T
(e.g.: Tuple
or Array
), and a function type F
,
and returns the iterable type obtained by mapping the type of each value in the iterable with the provided function type F
.
This is analogous to the JavaScript function map
.
按照 $ObjMap<T>
中的示例,我们假设 run
接受函数数组而不是对象,并映射它们,返回函数调用结果的数组。我们可以这样注释它的返回类型:
¥Following our example from $ObjMap<T>
, let's assume that run
takes an array of functions, instead of an object, and maps over them returning an array of the function call results. We could annotate its return type like this:
1// Function type that takes a `() => V` and returns a `V` (its return type)2type ExtractReturnType = <V>(() => V) => V3
4function run<A, I: Array<() => A>>(iter: I): $TupleMap<I, ExtractReturnType> {5 return iter.map(fn => fn());6}7
8const arr = [() => 'foo', () => 'bar'];9run(arr)[0] as string; // Works10run(arr)[1] as string; // Works11run(arr)[1] as boolean; // Error!
已删除的工具类型
¥Removed utility types
这些工具类型曾经存在,但在最新版本的 Flow 中不再存在。
¥These utility types used to exist, but no longer exist in latest version of Flow.
$Call<F, T...>
≤0.247{#toc-call}
¥NOTE: Please use Conditional Types or Indexed Access Types to extract types instead.
$Call<F, T...>
是一种类型,表示使用 0 个或多个参数 T...
调用给定 函数类型 F
的结果。这类似于在运行时调用函数(或更具体地说,类似于调用 Function.prototype.call
),但是是在类型级别;这意味着函数类型调用是静态发生的,即不是在运行时发生。
¥$Call<F, T...>
is a type that represents the result of calling the given function type F
with 0 or more arguments T...
.
This is analogous to calling a function at runtime (or more specifically, it's analogous to calling Function.prototype.call
), but at the type level; this means that function type calls happens statically, i.e. not at runtime.
让我们看几个例子:
¥Let's see a couple of examples:
1// Takes an object type, returns the type of its `prop` key2type ExtractPropType = <T>({prop: T, ...}) => T;3type Obj = {prop: number};4type PropType = $Call<ExtractPropType, Obj>; // Call `ExtractPropType` with `Obj` as an argument5type Nope = $Call<ExtractPropType, {nope: number}>; // Error! Argument doesn't match `Obj`.6
75 as PropType; // Works8true as PropType; // Error! PropType is a number
1// Takes a function type, and returns its return type2type ExtractReturnType = <R>(() => R) => R;3type Fn = () => number;4type ReturnType = $Call<ExtractReturnType, Fn>;5
65 as ReturnType; // Works7true as ReturnType; // Error! ReturnType is a number
$Call
非常强大,因为它允许你在类型域中进行调用,否则你必须在运行时执行此操作。类型域调用是静态发生的,并将在运行时被删除。
¥$Call
can be very powerful because it allows you to make calls in type-land that you would otherwise have to do at runtime.
The type-land calls happen statically and will be erased at runtime.
1// Getting return types:2function getFirstValue<V>(map: Map<string, V>): ?V {3 for (const [key, value] of map.entries()) {4 return value;5 }6 return null;7}8
9// Using $Call, we can get the actual return type of the function above:10type Value = $Call<typeof getFirstValue, Map<string, number>>;11
125 as Value;13true as Value; // Error! Value is a `number`14
15// We could generalize it further:16type GetMapValue<M> =17 $Call<typeof getFirstValue, M>;18
195 as GetMapValue<Map<string, number>>;20true as GetMapValue<Map<string, boolean>>;21true as GetMapValue<Map<string, number>>; // Error! value is a `number`
$ObjMap<T, F>
≤0.246{#toc-objmap}
注意:请改用 映射类型。
¥NOTE: Please use Mapped Types instead.
ObjMap<T, F>
接受 对象类型 T
和 函数类型 F
,并返回通过将对象中每个值的类型与提供的函数类型 F
进行映射而获得的对象类型。换句话说,$ObjMap
将为 T
中的每个属性值类型对给定函数类型 F
进行 调用(在类型级别),并从这些调用返回结果对象类型。
¥ObjMap<T, F>
takes an object type T
, and a function type F
, and returns the object type obtained by mapping the type of each value in the object with the provided function type F
. In other words, $ObjMap
will call (at the type level) the given function type F
for every property value type in T
, and return the resulting object type from those calls.
让我们看一个例子。假设你有一个名为 run
的函数,它接受 thunk 对象(() => A
形式的函数)作为输入:
¥Let's see an example. Suppose you have a function called run
that takes an object of thunks (functions in the form () => A
) as input:
1function run<O: {[key: string]: (...$ReadOnlyArray<mixed>) => mixed}>(o: O): $FlowFixMe {2 return Object.keys(o).reduce<{[string]: (...$ReadOnlyArray<mixed>) => mixed}>(3 (acc, k) => ({...acc, [(k: string)]: o[k]()}),4 {},5 );6}
该函数的目的是运行所有 thunk 并返回一个由值组成的对象。这个函数的返回类型是什么?
¥The function's purpose is to run all the thunks and return an object made of values. What's the return type of this function?
键是相同的,但值的类型不同,即每个函数的返回类型。在值级别(函数的实现),我们本质上是映射对象以生成键的新值。如何在类型级别上表达这一点?
¥The keys are the same, but the values have a different type, namely the return type of each function. At a value level (the implementation of the function) we're essentially mapping over the object to produce new values for the keys. How to express this at a type level?
这就是 ObjMap<T, F>
派上用场的地方
¥This is where ObjMap<T, F>
comes in handy
1// let's write a function type that takes a `() => V` and returns a `V` (its return type)2type ExtractReturnType = <V>(() => V) => V;3
4declare function run<O: {[key: string]: (...$ReadOnlyArray<mixed>) => mixed}>(o: O): $ObjMap<O, ExtractReturnType>;5
6const o = {7 a: () => true,8 b: () => 'foo'9};10
11run(o).a as boolean; // Works12run(o).b as string; // Works13run(o).b as boolean; // Error! `b` is a string14run(o).c; // Error! `c` was not in the original object
这对于表达操作对象值的函数的返回类型非常有用。例如,你可以使用类似的方法来提供 bluebird 的 Promise.props
函数的返回类型,该函数与 Promise.all
类似,但采用对象作为输入。
¥This is extremely useful for expressing the return type of functions that manipulate objects values.
You could use a similar approach (for instance) to provide the return type of bluebird's Promise.props
function,
which is like Promise.all
but takes an object as input.
这是该函数的可能声明,与我们的第一个示例非常相似:
¥Here's a possible declaration of this function, which is very similar to our first example:
1declare function props<A, O: {[key: string]: A}>(promises: O): Promise<$ObjMap<O, <T>(p: Promise<T> | T) => T>>>;2
3const promises = {a: Promise.resolve(42)};4props(promises).then(o => {5 o.a as 42; // Works6 o.a as 43; // Error! Flow knows it's 427});
$ObjMapi<T, F>
≤0.246{#toc-objmapi}
注意:请改用 映射类型。
¥NOTE: Please use Mapped Types instead.
ObjMapi<T, F>
与 ObjMap<T, F>
类似。不同之处在于,函数类型 F
将是 被称为,同时具有对象类型 T
的元素的键和值类型,而不仅仅是值类型。例如:
¥ObjMapi<T, F>
is similar to ObjMap<T, F>
. The difference is that function
type F
will be called with both the key and value types of the elements of
the object type T
, instead of just the value types. For example:
1const o = {2 a: () => true,3 b: () => 'foo'4};5
6type ExtractReturnObjectType = <K, V>(K, () => V) => { k: K, v: V };7
8declare function run<O: {...}>(o: O): $ObjMapi<O, ExtractReturnObjectType>;9
10run(o).a as {k: 'a', v: boolean}; // Works11run(o).b as {k: 'b', v: string}; // Works12run(o).a as {k: 'b', v: boolean}; // Error! `a.k` is "a"13run(o).b as {k: 'b', v: number}; // Error! `b.v` is a string14run(o).c; // Error! `c` was not in the original object
$ObjMapConst<O, T>
≤0.246{#toc-objmapconst}
注意:请改用 映射类型。
¥NOTE: Please use Mapped Types instead.
$ObjMapConst<Obj, T>
是 $ObjMap<Obj, F>
的特例,当 F
是常量函数类型时,例如 () => T
。你可以写 $ObjMapConst<Obj, T>
,而不是写 $ObjMap<Obj, () => T>
。例如:
¥$ObjMapConst<Obj, T>
is a special case of $ObjMap<Obj, F>
, when F
is a constant
function type, e.g. () => T
. Instead of writing $ObjMap<Obj, () => T>
, you
can write $ObjMapConst<Obj, T>
. For example:
1const obj = {2 a: true,3 b: 'foo'4};5
6declare function run<O: {...}>(o: O): $ObjMapConst<O, number>;7
8// newObj is of type {a: number, b: number}9const newObj = run(obj);10
11newObj.a as number; // Works12newObj.b as string; // Error! Property `b` is a number
提示:优先使用 $ObjMapConst
而不是 $ObjMap
(如果可能)来修复某些类型的 [invalid-exported-annotation]
错误。
¥Tip: Prefer using $ObjMapConst
instead of $ObjMap
(if possible) to fix certain
kinds of [invalid-exported-annotation]
errors.
$Partial
≤0.202部分的 的前别名。0.203 版本中删除了支持。
¥A former alias of Partial. Support was removed in version 0.203.
$Shape<T>
≤0.206{#toc-shape}
注意:该实用程序不安全 - 请使用上面记录的 Partial
将对象的所有字段设为可选。
¥NOTE: This utility is unsafe - please use Partial
documented above to make all of an object's fields optional.
类型 $Shape<T>
的变量(其中 T
是某种对象类型)可以分配给对象 o
,该对象包含 T
中包含的属性的子集。对于 T
的每个属性 p: S
,o
中 p
的潜在绑定类型必须与 S
兼容。
¥A variable of type $Shape<T>
, where T
is some object type, can be assigned objects o
that contain a subset of the properties included in T
. For each property p: S
of T
,
the type of a potential binding of p
in o
must be compatible with S
.
例如
¥For example
1type Person = {2 age: number,3 name: string,4};5// $FlowIgnore[deprecated-utility]6type PersonDetails = $Shape<Person>;7
8const person1: Person = {age: 28}; // ERROR: missing `name`9const person2: Person = {name: 'a'}; // ERROR: missing `age`10const person3: PersonDetails = {age: 28}; // OK11const person4: PersonDetails = {name: 'a'}; // OK12const person5: PersonDetails = {age: 28, name: 'a'}; // OK13const person6: PersonDetails = {age: '28'}; // ERROR: string is incompatible with number
注意:$Shape<T>
不等于 T
,其所有字段都标记为可选。特别是,Flow 不合理地允许 $Shape<T>
在多种情况下用作 T
。例如在
¥NOTE: $Shape<T>
is not equivalent to T
with all its fields marked as optional.
In particular, Flow unsoundly allows $Shape<T>
to be used as a T
in several
contexts. For example in
const personShape: PersonDetails = {age: 28};
personShape as Person;
Flow 会不健康地让最后一次演员成功。
¥Flow will unsoundly allow this last cast to succeed.
在某些情况下它也不等同于自身:
¥It is also not equivalent to itself in some contexts:
function f<T>(input: $Shape<T>): $Shape<T> {
return input; // ERROR: `T` is incompatible with `$Shape` of `T`
}
此工具类型已弃用,并将在将来删除 - 使用 Partial
代替。
¥This utility type is deprecated and will be deleted in the future -
use Partial
instead.