从可选构造函数参数的 return 类型推断类型

infer type from optional constructor function parameter's return type

type DefaultType = {.....};
class A<MyInferedType> {
  constructor(
    private readonly paramFunc: (response: MyInferedType) => any,
    private readonly optionalParamFunc?: () => Promise<MyInferedType>
  ) {}
  async doSomething() {
    // note the else branch! if optionalParamFunc is not defined i want to use a DefaultType value
    const result = this.optionalParamFunc ? this.optionalParamFunc() : {} as DefaultType ;
    this.paramFunc(result);
  }
}

我希望从 optionalParamFunc 中推断出 MyInferedType 如果将其传递给构造函数。如果没有通过,我希望它是DefaultType。 我在玩 infer 关键字,但没有成功。我想一些专家可以向我解释什么是正确的方法。

我应该可以按如下方式使用它:

const defVal: DefaultType = {...};
const inferedVal: AnyTypeOfChoice = {...};
const a = new A((defVal) => {...});
const a2 = new A((inferedVal) => {...}, async () => inferedVal);

playground link

您实际上并不需要条件类型的推理行为(即 infer 关键字)。一个简单的参数类型默认值似乎可以完成这项工作:

type DefaultType = { d: string };
class A<MyInferedType = DefaultType> {
  constructor(
    private readonly paramFunc: (response: MyInferedType) => any,
    private readonly optionalParamFunc?: () => Promise<MyInferedType>
  ) {}
}

type AnyTypeOfChoice  = {a: string }
const defVal: DefaultType = { d: ""};
const inferedVal: AnyTypeOfChoice = { a: ""};
const a = new A((defVal) => { defVal.d });
const a2 = new A((inferedVal) => { inferedVal.a }, async () => inferedVal);

Playground Link

关于实例化一个泛型类型参数值的问题,那是TS原则上不允许的。从打字的角度来看,检查 this.optionalParamFunc 和类型参数 MyInferedType 之间没有关系,所以就 ts 而言,你不能实例化 MyInferedType 因为你真的不知道它的全貌。

您可以使用类型断言来解决这个问题:

const result = this.optionalParamFunc ? await this.optionalParamFunc() : {d: "asdsad"} as any as MyInferedType;

请注意,我们可以构想一个实际 this.optionalParamFunc 未定义但没有类型参数 DefaultType 的实例化。 (new A<AnyTypeOfChoice>((inferedVal) => { inferedVal.a }))