Typescript 多泛型函数的推断签名
我无法匹配多个泛型函数的函数签名。我试图创建两个工厂函数,它们返回异步和同步结果。然而,typescript给了我一个实现错误。我不理解错误的原因,尤其是因为使用代码似乎没问题 实施:Typescript 多泛型函数的推断签名,typescript,typescript-generics,Typescript,Typescript Generics,我无法匹配多个泛型函数的函数签名。我试图创建两个工厂函数,它们返回异步和同步结果。然而,typescript给了我一个实现错误。我不理解错误的原因,尤其是因为使用代码似乎没问题 实施: class Item { constructor(public data: { id: string; name: string }) {} } type Factory<T extends any[], M> = (...args: T) => M type AsyncFactory&l
class Item {
constructor(public data: { id: string; name: string }) {}
}
type Factory<T extends any[], M> = (...args: T) => M
type AsyncFactory<T extends any[], M> = (...args: T) => Promise<M>
type FactoryHandler<T extends any[], M> = Factory<T, M> | AsyncFactory<T, M>
class Collection<
A extends any[],
M extends Item,
FF extends FactoryHandler<A, M>
> {
constructor(public factory: FF) {}
createItem(...args: A): ReturnType<FF> extends Promise<M> ? Promise<M> : M {
return this.factory(...args) // error
/*
Type 'M | Promise<M>' is not assignable to type 'ReturnType<FF> extends Promise<M> ? Promise<M> : M'.
Type 'M' is not assignable to type 'ReturnType<FF> extends Promise<M> ? Promise<M> : M'.
Type 'Item' is not assignable to type 'ReturnType<FF> extends Promise<M> ? Promise<M> : M'.ts(2322)
*/
}
}
Typescript将返回值视为两种可能性的联合
M | Promise
。此联合不可分配给您的条件。Typescript不够聪明,无法理解哪些情况返回M
,哪些情况返回Promise
class Collection<
A extends any[],
M extends Item | Promise<Item>
> {
constructor(public factory: (...args: A) => M) {}
createItem(...args: A): M {
return this.factory(...args);
}
}
使用作为
断言
简单的解决方法是使用As
断言告诉TypescriptcreateItem
的返回类型与this.factory
的返回类型匹配,后者是typeFF
createItem(...args: A): ReturnType<FF> {
return this.factory(...args) as ReturnType<FF>;
}
在返回类型中使用条件总是很粗糙的。你可能必须坚持这一点
将此.factory(…args)作为ReturnType返回
或者,您可以始终返回一个承诺
,无论工厂函数是否为异步
<代码>异步createItem(…args:A):承诺{返回this.factory(…args);}作为返回类型
没有帮助。对于第二种情况:Promise
,它推断所有create
函数变体都返回一个Promise。对于第一种情况,您不需要在返回中使用条件。只需执行createItem(…args:A):ReturnType{将this.factory(…args)作为ReturnType;}
。第二,我们通过使方法异步,使非异步函数返回一个Promise
。我不认为这是您想要的,但我有点喜欢它,因为它是一种抽象级别,允许您以相同的方式处理所有集合
对象,而不管它们的工厂是否异步。因此,它将改变您使用非异步集合的方式,因为您必须将它们视为异步的。哦,我明白了,我已经删除了条件返回,现在就必须这样做。我希望用户明确知道create
函数是否返回承诺。在某些情况下,会首选同步返回。谢谢,“无断言”是一个非常干净的解决方案。我现在无法更改M
泛型,因此我创建了另一个R extends M | Promise
,并将其用于返回类型。您会选择哪种解决方案?我会选择“无断言”。一般来说,使用更少的泛型变量会更好(这让我现在想回去用FF
!)编写它)。我包含了这两种方法,因为我认为类中可能还有其他方法需要修改它们的类型,以便更容易实现断言。
class Collection<
A extends any[],
M extends Item | Promise<Item>
> {
constructor(public factory: (...args: A) => M) {}
createItem(...args: A): M {
return this.factory(...args);
}
}