Given
type UnionType = 'prop1' | 'prop2' | 'prop3';
type DerivedType = {
prop1: string;
prop2: number;
prop3: boolean;
};
Is there a way to declare DerivedType so that if I add a member to UnionType without adding the corresponding property to DerivedType I'll get a TypeScript error?
If the types of the properties were all the same this would be trivial, but they aren't.
I don't want Record<UnionType, any> - I want specific types for each property.
The actual use case involves a union type that is keyof a different type; the "derived" type specifies configurations for each of the properties. The goal is to keep all of these types in sync.
Assuming you can't or don't want to refactor so that
UnionTypeis defined in terms ofDerivedTypeor so that bothUnionTypeandDerivedTypeare defined in terms of something else, you can write your ownCheckKeys<K, T>utility type which will evaluate toT, but issue a compiler error unless the keys ofTare seen to be exactlyKwith nothing missing or extra (although there might be edge cases).Here's one way to do it:
Here
Tis constrained so that it definitely has all ofKas keys (since it extendsRecord<K, any>using theRecordutility type), and also (via intersection) any keys ofTthat are not inK(using theExcludeutility type) must have properties of the impossiblenevertype. Since onlyneveris assignable toneverand you're not likely to set property types toneverto begin with, this should more or less enforce the restriction you're looking for. Let's test it:Looks good.
DerivedTypeis still the same type as before, and it compiles without error. But if you add or remove a key, you get the requisite compiler error mentioning where the problem is.Playground link to code