我在创建函数签名时遇到问题,该函数签名可以基于具有该类型属性的对象数组来推断联合类型。如果仅是对象/类型的数组,它就可以工作,但是我觉得它也应该以这种方式工作。如果不清楚,在下面的示例中,我希望推断的函数签名为func<ClassA | ClassB>(arr: Array<Config<ClassA | ClassB>>)
interface Base {
thing: number;
}
class ClassA implements Base {
public propA!: number;
public thing!: number;
}
class ClassB implements Base {
public propB!: number;
public thing!: number;
}
interface Config<T extends Base> {
cls: new() => T;
}
function func<T extends Base>(arr: Array<Config<T>>) {}
func([]);
func([
{ cls: ClassA },
]);
// Doesn't compile
func([
{ cls: ClassA },
{ cls: ClassB },
]);
// Does compile
func<ClassA | ClassB>([
{ cls: ClassA },
{ cls: ClassB },
]);
这里有一个关于stackblitz的例子 https://stackblitz.com/edit/typescript-array-subprop-type-infer
如果您查看第42行,则可以看到它不是子属性时正确地将类型推断为ClassA | ClassB
。但是在第24行,它没有将其推断为该类型。它仅获取数组中第一个元素的类型,因此将鼠标悬停在其上时的函数签名为ClassA
(或在stackblitz上显示基类)。我希望它能与任何数量的类型一起使用,因此将它们添加到功能模板参数中是不够的。
答案 0 :(得分:1)
问题是您正试图强制TypeScript推断
Array<Config<ClassA | ClassB>>
在尝试推断时
Array<Config<ClassA> | Config<ClassB>>
通常,这些关系是不可互换的。尽管作为声明可能会感到尴尬,但您可以做的是允许推断正确类型的方法是
function func<T extends Config<Base>>(arr: Array<T>) {}
但随后必须进行显式调用
func<Config<ClassA> | Config<ClassB>>([
{ cls: ClassA },
{ cls: ClassB },
]);