【发布时间】:2020-07-14 01:50:52
【问题描述】:
在玩 TS 3.7.2 时,我发现了一个奇怪的边缘情况,现在我很想知道更多关于函数中的类型推断在这种特定情况下是如何工作的。
interface A {
functions: { t: number, a: { test: number }; };
}
interface B {
functions: { t: number, b: { ciao: number }; };
}
function combineStuff<TNamespace extends {}>(stuff: { functions: Partial<TNamespace> }[]): TNamespace {
// Implementation irrelevant for the question
return {functions: merge({}, ...stuff.map(s => s.functions))} as any;
}
const a: A = { functions: { t: 1, a: { test: 1 } } };
const b: B = {functions: { t: 1, b: { ciao: 2 } }};
const c = combineStuff([a, b]);
c.a.test;
c.b.ciao; // Error. Why is that?
const d = combineStuff<A['functions'] & B['functions']>([a, b]);
d.a.test;
d.b.ciao; // Works well
我的预期是 c.b.ciao 和 d.b.ciao 都是类型安全的,但访问 c.b.ciao 会导致错误。
从这个简单的例子看来,泛型类型可以从数组的元素中自动推断出来,这一假设也得到了以下事实的支持:在调用 combineStuff<A['functions'] & B['functions']>([a, b]); 中,TS 编译器验证了 a 和b 实际上是正确的。
此外,类型推断对于数组a 的第一个元素可以正常工作,我可以安全地访问c.a.test。
为什么我需要显式地将泛型类型提供给combineStuff() 以获得正确的结果?为什么对数组第一个元素的推断工作正常?
【问题讨论】:
标签: typescript typescript-typings typescript-generics