Reputation: 141522
How can we model this without creating a union type that has each possible object?
type ValidRootPropertyNames =
'Property1' |
'Property2';
type ObjectWithRootPropertyNameFromList =
{ Property1: string; } |
{ Property2: string; };
const obj1: ObjectWithRootPropertyNameFromList = { // okay
Property1: 'foo',
};
const obj2: ObjectWithRootPropertyNameFromList = { // okay
Property2: 'foo',
};
const obj3: ObjectWithRootPropertyNameFromList = { // error
Property3: 'foo',
};
The above does what we need; the problem is that it becomes cumbersome when there are dozens of valid property names.
Upvotes: 1
Views: 46
Reputation: 249666
You can use the distributive behavior of conditional types to create the union automatically from the union of keys:
type ValidRootPropertyNames =
'Property1' |
'Property2';
type ObjectWithRootPropertyNameFromList =
ValidRootPropertyNames extends infer T ? // Introduce a type parameter to have distributive behavior
T extends string ? Record<T, string> : never : never;
const obj1: ObjectWithRootPropertyNameFromList = { // okay
Property1: 'foo',
};
const obj2: ObjectWithRootPropertyNameFromList = { // okay
Property2: 'foo',
};
const obj3: ObjectWithRootPropertyNameFromList = { // error
Property3: 'foo',
};
Upvotes: 1