I have a enum and I let each value of the enum as a key in my interface whose value is specific to the key.
Example:
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,
}
This works well, but I want have similar code in several places and I want them to give me compile errors when there's a new entry in the enum. Currently, this doesn't do any exhaustive check, so it does not. Is it possible to achieve that with TypeScript?
CodePudding user response:
You probably want to make use of the Record utility type, which works great with enums.
Something like:
enum Fruits {
Apple = 'Apple',
Banana = 'Banana',
}
type Slicer = Function; // Quick example case
type FruitSlicers = Record<Fruits, Slicer>; // <- Ensures every enum value is a key
const fruitSlicers: FruitSlicers = {
[Fruits.Apple]: () => {},
[Fruits.Banana]: () => {},
};
Now if I add another Fruit:
enum Fruits {
Apple = 'Apple',
Banana = 'Banana',
Cherry = 'Cherry',
}
I get:
Property 'Cherry' is missing in type '{ Apple: () => void; Banana: () => void; }' but required in type 'FruitSlicers'
CodePudding user response:
For this you will need type compatibility checks. My recommended library for this is ts-expect: https://github.com/TypeStrong/ts-expect
Here is a complete sample (I've inlined expectType and TypeOf from ts-expect):
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 ❌
