ed'
ed'

Reputation: 1895

Typescript index signatures

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

Answers (2)

Priyal
Priyal

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

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

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

Related Questions