【发布时间】:2019-08-05 00:03:50
【问题描述】:
我正在尝试键入一个函数,该函数接受一个将一系列项目减少为一个累积值的参数。这是我所拥有的简化:
// A stub type for the items
interface Item { t: 'item'; }
function paginate<A>(reduce: (acc: A, item: Item, index: number) => A): Promise<A> {
// ... stub for actual implementation ...
return true as unknown as Promise<A>;
}
如果我调用这个函数,我不会得到我想要的推理类型。我希望当reduce 的返回类型已知时,第一个参数(acc)也应该被推断为该类型。
// expected: Promise<number>, inferred: Promise<{}>
const result = paginate((acc, item, index) => {
acc; // expected: number, inferred: {}
item; // expected: Item, inferred: Item
index; // expected number, inferred: number
return 5;
});
我尝试使用带有推理的条件类型来解决这个问题,但是我尝试过的所有变体都失败了,因为它们没有将acc 的泛型类型参数限制为任何特定的东西,或者因为推理是递归的而失败.我不完全确定。
type Reducer<A> = (acc: A, item: Item, index: number) => A;
type Accumulator<Reduce> = Reduce extends (acc: infer A, item: Item, index: number) => infer A ? A : never;
// Probably too loose (using an any)
function paginateA<R extends Reducer<any>>(reduce: R): Promise<Accumulator<R>> {
// ...
return true as unknown as Promise<Accumulator<R>>;
}
// expected: Promise<number>, inferred: Promise<number>
const resultA = paginateA((acc, item, index) => {
acc; // expected: number, inferred: any
item; // expected: Item, inferred: Item
index; // expected number, inferred: number
return 5;
});
// Probably too recursive (tried to circuit-break with only inferring the return type first)
function paginateB<R extends Reducer<ReturnType<R>>>(reduce: R): Promise<Accumulator<R>> {
// ...
return true as unknown as Promise<Accumulator<R>>;
}
// expected: Promise<number>, inferred: Promise<any>
const resultB = paginateB((acc, item, index) => {
acc; // expected: number, inferred: any
item; // expected: Item, inferred: Item
index; // expected number, inferred: number
return 5;
});
是否有任何技术可以“断路”递归条件类型推断?我看到了Anders mention that some class of recursive inference is okay(即使快速信息将类型显示为any),但我无法理解发生这种情况的条件。
我还缺少其他一些技术吗? paginateA() 似乎效果最好,因为至少它得到了resultA 的类型是正确的。有什么原因吗?
这里有一个playground with all the above code 来操作。
【问题讨论】:
-
嗯,在我的 TS3.4 预览中(使用
typescript@next)我得到了Promise<number>forresult,但我在 TS3.3 及以下看到的是Promise<{}>。也许只等几个星期?
标签: javascript typescript functional-programming type-inference conditional-types