[英]Typescript failed to infer generic type
我正在使用以下代码段。 当我删除行validate: (...) => {}
, A
被正确推断为rule1: { v: number }
。 但是,当该行没有被移除时, A
被推断为unknown
。 任何想法是什么导致了这个以及如何解决它? 提前致谢 :)
type Arguments<A> = {
[K in keyof A]: {
args: {
[K1 in keyof A[K]]: {
assert?: (arg: unknown) => arg is A[K][K1];
}
};
validate?: (value: unknown, args: A[K]) => unknown;
}
}
function test<A>(args: Arguments<A>) {}
test({
rule1: {
args: {
v: {
assert: (arg): arg is number => typeof arg === 'number',
}
},
validate: (value, args) => {
}
}
});
这里的问题是编译器需要在同一个对象中同时推断泛型类型参数和未注释回调参数的类型,并且它不能真正做到一致。 这是一个已知的设计限制; 参见microsoft/TypeScript#12621和microsoft/TypeScript#26418等。 这里的简短回答是您要么必须放弃这些推理之一(通过手动指定泛型类型参数或手动注释回调参数),要么必须将单个对象分解为多个对象,以便编译器可以分阶段进行多次推理。
我将在此处介绍的解决方法是一个辅助函数,它从两个单独的对象构建单个对象。 第一个对象将用于推断泛型类型参数,然后将用于第二个对象中回调参数的上下文类型。 (我在评论中称之为“柯里化”,但它真的不是柯里化,对术语错误表示抱歉)
const arg = function <T>(
args: { [K in keyof T]: {
assert?: (arg: unknown) => arg is T[K];
} },
validate?: (value: unknown, args: T) => unknown
) {
return ({ args, validate });
}
arg()
函数接受两个参数args
和validate
,并将它们组合成一个对象。 现在,当您调用test()
时,您可以使用arg()
来构建每个属性:
test({
rule1: arg({
v: {
assert: (arg): arg is number => typeof arg === 'number',
}
}, (value, args) => { }
)
});
这里arg()
的类型参数被推断为{v: number}
,因此test()
的类型参数现在可以根据需要正确推断为{rule1: {v: number}}
。 它并不完美,但它是我目前能想到的最好的。 好的,希望有帮助; 祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.