流类型 - 将函数对象映射到函数结果
Flow types - map Object of functions to function results
我正在尝试使用流程键入一个函数,给定一个对象类型,它接受一个对象,其中每个 属性 被一个 "create" 函数替换,创建值。我希望能够使用键入的 $ElementType
将值类型映射到 $Keys
,但它似乎没有正确关联键和值。
这是一个简化的例子:
// @flow
type TestType = {
foo: number,
bar: string,
}
declare function create<
K: $Keys<TestType>,
V: $ElementType<TestType, K>,
O: {[K]: () => V}
>(obj: O): TestType
const tmp = create({
foo: () => 5,
bar: () => 'whatever',
})
但流报告每个类型与相反键的值不兼容。例如。 foo
的值与 bar
的值不兼容:
Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ tmp/syntax/flowTest.js:15:14
Cannot call create with object literal bound to obj because number [1] is
incompatible with string [2] in the return value of property foo.
[2] 5│ bar: string,
:
11│ O: {[K]: () => V}
12│ >(obj: O): TestType
13│
14│ const tmp = create({
[1] 15│ foo: () => 5,
16│ bar: () => 'whatever',
17│ })
18│
19│ // type TodoValues = {
20│ // todos: Array<string>,
Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ tmp/syntax/flowTest.js:16:14
Cannot return 'whatever' because string [1] is incompatible with number [2].
[2] 4│ foo: number,
:
13│
14│ const tmp = create({
15│ foo: () => 5,
[1] 16│ bar: () => 'whatever',
17│ })
18│
19│ // type TodoValues = {
这两个 properties foo
/ bar
中的一个可以传递给 obj
param 函数 创建。你不能把它们放在一起,因为你有 UnionType
.
K: $Keys<TestType>, // UNION: number | string
V: $ElementType<TestType, K>, // UNION: foo | bar
O: {[K]: () => V} // UNION: foo: () => number | bar: () => string
这个有效:
type TestType = {
foo: number,
bar: string,
}
declare function create<
K: $Keys<TestType>,
V: $ElementType<TestType, K>,
O: {[K]: () => V}
>(obj: O): TestType
const foo = create({ foo: () => 5 })
const bar = create({ bar: () => 'whatever' })
我认为 Flow $ObjMap
example 非常接近您想要的。它基本上开箱即用(将 run
重命名为 create
):
// let's write a function type that takes a `() => V` and returns a `V` (its return type)
type ExtractReturnType = <V>(() => V) => V;
declare function create<O: {[key: string]: Function}>(o: O): $ObjMap<O, ExtractReturnType>;
const o = {
foo: () => 0,
bar: () => 'foo',
baz: () => true,
};
type TestType = {
foo: number,
bar: string,
baz: number, // Error since true is not a number
}
const p: TestType = create(o);
我正在尝试使用流程键入一个函数,给定一个对象类型,它接受一个对象,其中每个 属性 被一个 "create" 函数替换,创建值。我希望能够使用键入的 $ElementType
将值类型映射到 $Keys
,但它似乎没有正确关联键和值。
这是一个简化的例子:
// @flow
type TestType = {
foo: number,
bar: string,
}
declare function create<
K: $Keys<TestType>,
V: $ElementType<TestType, K>,
O: {[K]: () => V}
>(obj: O): TestType
const tmp = create({
foo: () => 5,
bar: () => 'whatever',
})
但流报告每个类型与相反键的值不兼容。例如。 foo
的值与 bar
的值不兼容:
Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ tmp/syntax/flowTest.js:15:14
Cannot call create with object literal bound to obj because number [1] is
incompatible with string [2] in the return value of property foo.
[2] 5│ bar: string,
:
11│ O: {[K]: () => V}
12│ >(obj: O): TestType
13│
14│ const tmp = create({
[1] 15│ foo: () => 5,
16│ bar: () => 'whatever',
17│ })
18│
19│ // type TodoValues = {
20│ // todos: Array<string>,
Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ tmp/syntax/flowTest.js:16:14
Cannot return 'whatever' because string [1] is incompatible with number [2].
[2] 4│ foo: number,
:
13│
14│ const tmp = create({
15│ foo: () => 5,
[1] 16│ bar: () => 'whatever',
17│ })
18│
19│ // type TodoValues = {
这两个 properties foo
/ bar
中的一个可以传递给 obj
param 函数 创建。你不能把它们放在一起,因为你有 UnionType
.
K: $Keys<TestType>, // UNION: number | string
V: $ElementType<TestType, K>, // UNION: foo | bar
O: {[K]: () => V} // UNION: foo: () => number | bar: () => string
这个有效:
type TestType = {
foo: number,
bar: string,
}
declare function create<
K: $Keys<TestType>,
V: $ElementType<TestType, K>,
O: {[K]: () => V}
>(obj: O): TestType
const foo = create({ foo: () => 5 })
const bar = create({ bar: () => 'whatever' })
我认为 Flow $ObjMap
example 非常接近您想要的。它基本上开箱即用(将 run
重命名为 create
):
// let's write a function type that takes a `() => V` and returns a `V` (its return type)
type ExtractReturnType = <V>(() => V) => V;
declare function create<O: {[key: string]: Function}>(o: O): $ObjMap<O, ExtractReturnType>;
const o = {
foo: () => 0,
bar: () => 'foo',
baz: () => true,
};
type TestType = {
foo: number,
bar: string,
baz: number, // Error since true is not a number
}
const p: TestType = create(o);