A built-in associative array type

Topics: Language Specification
Oct 7, 2012 at 11:08 AM
Edited Oct 7, 2012 at 11:09 AM

It'd be great to have a built in type for associative arrays/dictionaries similar to the built-in array type.

I know that they can be emulated with objects, but such constructs do not provide type checks.

This works:

var array: string[] = []; // only accepts strings
array.push( 'Hi there' ); // ok
array.push( 1 ); // compiler warning

This would be nice:

var dict: (string, Person)[] = [];
dict['Matt'] = new Person(); // ok
dict['Chris'] = new Car(); //compiler warning
dict[1] = new Person(); // compiler warning
Developer
Oct 7, 2012 at 3:13 PM

You can do this using index signatures and you get the expected type checking. For example:

var dict: { [index: string]: Person; } = {};
dict['Matt'] = new Person(); // ok
dict['Chris'] = new Car(); //compiler warning
dict[1] = new Person(); // compiler warning

Anders

Oct 7, 2012 at 3:41 PM

That's great, thank you!

Oct 7, 2012 at 5:33 PM

One last thing: Why is this invalid?

private virtualKeys: { [index: number]: number; } = {} //Cannot convert '{}' to '[index: number] => number': Index signatures of types '{}' and '[index: number] => number' are incompatible

What's the correct syntax then?

Oct 7, 2012 at 6:38 PM

I don't think there is a correct syntax to annotate non-existing javascript. Object keys are transformed to strings if their type is not a string:

var key = 4;

var obj = { key: 4 }

will actually result in { '4' : 4 }, which is [index: string]: number; indeed.

Coordinator
Oct 8, 2012 at 6:09 PM

This comes up with defaults, too.

var x : {foo: number;} = {};
var y = <{foo:number;}>{};

The first line will have a type error because you're trying to satisfy the requirement of an object with a foo member with an object without a foo member.  The idiomatic way of writing the same thing is the second line, where you like the compiler infer the type and use an annotation instead.