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

我无法匹配多个泛型函数的函数签名。我试图创建两个工厂函数,它们返回异步同步结果。然而,typescript给了我一个实现错误。我不理解错误的原因,尤其是因为使用代码似乎没问题

实施:

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
断言告诉Typescript
createItem
的返回类型与
this.factory
的返回类型匹配,后者是type
FF

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); 
  }
}