徹底的な列挙型チェックを使用したTypeScriptインターフェイスの入力

1
2022.01.12

私は列挙型を持っており、私は値がキーに固有である私のインターフェイスのキーとして列挙型の各値をしましょう。

例:

enum Fruits {
  Apple = "Apple",
  Banana = "Banana",
}

// EDIT: These slicers can have completely different shapes.
interface AppleSlicer { foo: () => string }
interface BananaSlicer { bar: () => number }

interface FruitSlicers {
  [Fruits.Apple]: AppleSlicer,
  [Fruits.Banana]: BananSlicer,
}

これはうまくいきますが、いくつかの場所に似たコードを持ちたいし、enumに新しいエントリがあるときにコンパイルエラーを与えてほしい。現在、これは完全なチェックを行わないので、そうではありません。TypeScriptでそれを達成することは可能ですか?

回答
2
2022.01.13

このためには、型互換性チェックが必要です。私の推奨ライブラリは ts-expectです : https://github.com/TypeStrong/ts-expect

完全なサンプルを次に示します (ここでは、ts-expect から expectTypeTypeOf をインライン化しました)。

export const expectType = <Type>(value: Type): void => void 0;
export type TypeOf<Target, Value> = Exclude<Value, Target> extends never
  ? true
  : false;

type AppleSlicer = { apples: number }
type BananaSlicer = { bananas: number }

enum Fruits {
  Apple = "Apple",
  Banana = "Banana",
}

type FruitSlicersComplete = {
  [Fruits.Apple]: AppleSlicer,
  [Fruits.Banana]: BananaSlicer,
}
type FruitSlicersIncomplete = {
  [Fruits.Apple]: AppleSlicer,
  // [Fruits.Banana]: BananaSlicer,
}

type FruitSlicersExhaustive = {[key in Fruits]: any}

expectType<TypeOf<FruitSlicersExhaustive,FruitSlicersComplete>>(true); // Success ✅
expectType<TypeOf<FruitSlicersExhaustive,FruitSlicersIncomplete>>(true); // Error ❌