Reputation: 1895
I wish to restrict the assignable types of an object to a specific type. Example, an object where all keys must have number
values, such as below:
interface NumberMap {
[key: string]: number;
}
This works for enforcing the value restriction however I then won't be able to determine what keys actually exist inside the map
variable.
const map: NumberMap = {
one: 1,
two: 2,
three: 3,
};
// no error, but incorrect, this key does *not* exist
const lol = map.weoiroweiroew;
// Also cannot do this
type MyKeys = keyof map;
Is there a way to enforce an index signature without losing the information of what keys the object implementing that signature has?
Upvotes: 9
Views: 4153
Reputation: 484
How about this ? I think this will restrict your objects keys to the given 3 indexes
type Index = 'one' | 'two' | 'three'
type NumberMap = { [k in Index]?: number }
Upvotes: 2
Reputation: 249506
The only way to do both restrict values, and preserve type information about what keys are actually in the implementing type is to use a generic helper function. The function will enforce that the object literal extends the interface, but it will infer the actual type of the object literal:
interface NumberMap {
[key: string]: number;
}
function createNumberMap<T extends NumberMap>(v: T) {
return v;
}
const map = createNumberMap({
one: 1,
two: 2,
three: 3,
// no: '' // error
});
map.one //ok
map.no //error
Upvotes: 7