繁体   English   中英

基于字段的 TypeScript 泛型推断

[英]TypeScript Generic infer based on field

enum Letter {
  A = "A",
  B = "B",
  C = "C"
}

export type EntityT<T extends Letter = Letter> = T extends Letter.A
  ? { a: number }
  : T extends Letter.B
  ? { b: string }
  : T extends Letter.C
  ? { c: string }
  : never;

type DeltaT<T extends EntityT> = _DeltaT<T, keyof T>;

export type _DeltaT<E extends EntityT, K extends keyof E> = {
  key: K;
  oldValue: E[K];
  newValue: E[K];
};

export type ProblemT<T extends Letter = Letter> = EntityT<T> extends infer E
  ? {
      id: string;
      type: T;
      delta: DeltaT<E>[];
      oldEntity: E;
      newEntity: E;
    }
  : never;

const testCase: ProblemT<Letter.A> = {
  id: "id",
  type: Letter.A,
  delta: [{ key: "a", oldValue: 1, newValue: 2 }],
  oldEntity: { a: 1 },
  newEntity: { a: 2 }
};

function myFunc<T extends Letter>(e: ProblemT<T>) {
  switch (e.type) {
    case Letter.A: {
      const uselessConversion = e as ProblemT<Letter.A>;
      return uselessConversion.newEntity.a;
    }
    case Letter.B: {
      const uselessConversion = e as ProblemT<Letter.B>;
      return uselessConversion.newEntity.b;
    }
    case Letter.C: {
      const uselessConversion = e as ProblemT<Letter.C>;
      return uselessConversion.newEntity.c;
    }
  }
}

我想声明一个类型ProblemT ,它取决于他的type键,将在oldEntitynewEntity返回不同的值。 我想使用 switch 运行myFunc而无需手动转换对象,TypeScript 将根据type属性推断type 但效果不佳。 如何让开关自动推断类型而不需要转换。 有没有更好的方法来声明ProblemT不同类型,以便 switch 可以推断出它?

这是TypeScript 游乐场的链接

请注意,诸如Letter.A | Letter.B类的类型 Letter.A | Letter.B还扩展了Letter ,因此编译器不知道事物像它们一样受到约束。

像这样的事情会起作用:

enum Letter {
  A = "A",
  B = "B",
  C = "C"
}

export type EntityT<T extends Letter> =
  T extends Letter.A ? { a: number }
  : T extends Letter.B ? { b: string }
  : T extends Letter.C ? { c: string }
  : never;

export type DeltaT<T extends Letter, K = keyof EntityT<T>> = K extends keyof EntityT<T>
  ? {
    key: K;
    oldValue: EntityT<T>[K];
    newValue: EntityT<T>[K];
  }
  : never;

export type ProblemT<T extends Letter> = {
  id: string;
  type: T;
  delta: DeltaT<T>[];
  oldEntity: EntityT<T>;
  newEntity: EntityT<T>;
};

function myFunc(e: ProblemT<Letter.A> | ProblemT<Letter.B> | ProblemT<Letter.C>) {
  switch (e.type) {
    case Letter.A: return e.newEntity.a;
    case Letter.B: return e.newEntity.b;
    case Letter.C: return e.newEntity.c;
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM