簡體   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