ken ken - 1 month ago 15
TypeScript Question

Typing a constrained dictionary with TypeScript

I have a TypeScript 2.0 project where I'd like to define an immutable Map using

Immutable.js
. In particular I'd like to constrain the keys of the Map to a known set; something like the following:

type ConstrainedKeys = 'foo' | 'bar' | 'baz';
interface INameValuePair {
name: string;
value: string;
};
const dictionary = Immutable.Map<ConstrainedKeys, NameValuePair>(response);


Where the
response
might be something like:

{
foo: {
name: 'foo',
value: 'typing is fun'
}
}


But when I try and reference
dictionary.foo.value
I get the Typescript error:


[ts] Property 'foo' does not exist on type 'Map<ConstrainedKeys,INameValuePair>'.

Answer

Immutable.Map instances don't have properties for the entries, you need to access them like so:

let foo = dictionary.get("foo");

If you want to be able to access it like dictionary.foo then you need to change the instances yourself, or you can use a Proxy:

const map = Immutable.Map<ConstrainedKeys, INameValuePair>({
    foo: {
        name: 'foo',
        value: 'typing is fun'
    }
});

const dictionary = new Proxy(map, {
    get: (target: Immutable.Map<ConstrainedKeys, INameValuePair>, name: ConstrainedKeys) => {
        if ((target as any)[name]) {
            return (target as any)[name];
        }
        return target.get(name);
    }
}) as Immutable.Map<ConstrainedKeys, INameValuePair> & { foo: INameValuePair };

console.log(dictionary.foo); // {name: "foo", value: "typing is fun"}
console.log(dictionary.get("foo")); // {name: "foo", value: "typing is fun"}
Comments