来自枚举的Typescript类型推断引发“类型实例化过深,甚至可能是无限的。”

时间:2019-10-18 03:59:32

标签: typescript

我有一种情况,我想将一个枚举映射到一个类型,以便用户可以调用一个函数,并基于传递给第一个参数的枚举,可以推断出第二个参数的类型。

我将其设置如下:

enum MyEnum {
  One,
  Two
}

interface OnePayload {
  one: string;
}
interface TwoPayload {
  two: string;
}

type FuncPayload<T> = T extends MyEnum.One
  ? OnePayload
  : T extends MyEnum.Two
  ? TwoPayload
  : any;

const func = <T extends MyEnum>(key: T, payload?: FuncPayload<T>) => {
  return payload;
};

可用于以下用途:

func(MyEnum.One,{one: 'a'}); // OK
func(MyEnum.Two,{one: 'a'}); // Throws type error
func(MyEnum.Two,{two: 'a'}); // OK

这很好用,除了在我的示例中,我有100〜个枚举值要映射到它们各自的类型。一旦我在FuncPayload类型中添加了许多条件,每当我使用该类型时,它都会引发Type instantiation is excessively deep and possibly infinite.错误。

有没有一种更好的方法来实现这一目标?或b)使用此方法解决此错误的方法?

2 个答案:

答案 0 :(得分:0)

您是否考虑过改用Union TypesType Guards,这样就不需要实际传递枚举类型了?

interface PayloadA {
  one: string;
}
interface PayloadB {
  two: string;
}

function isPayloadA(object: PayloadA | PayloadB): object is PayloadA {
    return (object as PayloadA).one !== undefined;
}

function myOperation(payload: (PayloadA|PayloadB)) {
  if (isPayloadA(payload)) {
    // payload is now strongly typed as PayloadA
  }
}

我想这最终取决于您要完成的工作。您的func函数应该做什么?强力投射松散类型的对象?

答案 1 :(得分:0)

找到了行之有效的东西:

enum MyEnum {
  One,
  Two
}

interface OnePayload {
  one: string;
}
interface TwoPayload {
  two: string;
}

interface FuncPayloadMap {
  [MyEnum.One]: OnePayload;
  [MyEnum.Two]: TwoPayload;
}

const func = <T extends MyEnum>(key: T, payload?: FuncPayloadMap[T]) => {
  return payload;
};

我想您可以使用接口将每个枚举值映射到接口,然后只使用泛型类型在映射中引用正确的接口。