【发布时间】:2021-10-26 15:32:31
【问题描述】:
尝试创建一个简单的实用程序,它可以:
- 按原样返回给定数组
- 或根据给定的可选参数进行转换。 这是代码:
type MapperFn<T, U> = (val: T) => U;
interface mapperOpts<T,U> {
cb?: MapperFn<T,U>
}
interface mapper {
map<T, U, Z extends mapperOpts<T,U>>(arr: Array<T>, opts: Z): Z extends { cb: MapperFn<T,U> } ? U[]: T[];
}
const obj: mapper = {
map: (arr, { cb }) => {
if (!cb) return arr;
return arr.map(cb);
}
}
const arr: number[] =[1,2,3];
const result = obj.map(arr, {cb: (element) => element.toString() }); // should be typed as `string[]`
const result2 = obj.map(arr, { cb: (element) => element+1 }); // should be typed as `number[]`
const result3 = obj.map(arr, {}); // should be types as `number[]`
但是,我收到了错误:
Type '<T, U, Z extends mapperOpts<T, U>>(arr: T[], { cb }: Z) => T[] | U[]' is not assignable to type '<T, U, Z extends mapperOpts<T, U>>(arr: T[], opts: Z) => Z extends { cb: MapperFn<T, U>; } ? U[] : T[]'.
Type 'T[] | U[]' is not assignable to type 'Z extends { cb: MapperFn<T, U>; } ? U[] : T[]'.
Type 'T[]' is not assignable to type 'Z extends { cb: MapperFn<T, U>; } ? U[] : T[]'.
请注意,result 和 result2 被标记为 unknown[],这可能意味着来自回调函数的参数类型推断无法正常工作。
我错过了什么?
【问题讨论】:
-
U作为单独的类型参数没有合理的推理站点;你最好把它排除在外并从Z推断它,比如this。这能满足你的需求吗? (我不明白你的一些用例,其中result2将是number[],尽管在各个方面都与result1相同,或者为什么你期望number而不是number[]而不是result3。哈!如果这些是错误,请修复它们,这样你就有一个真正的minimal reproducible example)。如果是这样,我会写一个答案;如果没有,请详细说明什么不适合您。 -
对不起!我粘贴了错误的链接。我已经更正了源代码和打字稿游乐场链接。我看到了你的链接,这似乎是我想要的!我最初是从这个开始的:tsplay.dev/WPjqqN 工作正常,并认为我可以从那里继续前进。您能否进一步解释一下没有合理的 U 推断站点作为单独的类型参数,或者指出一个来源以便我更好地理解为什么会发生这种情况?
标签: typescript type-inference optional-parameters conditional-types