Reputation: 1694
While trying to use the map type, I have repeatedly shot myself in the foot by trying to get and set elements using square brackets. I realize that I need to be using map.get(key)
and map.set(key,value)
but after using Python and C# dictionaries for so long, I'm having a hard time getting this through my thick skull.
let m = new Map<string, string>();
// This doesn't generate any error, though it
// doesn't do what someone might assume it
// would (doesn't add an element to the map)
m["foo"] = "bar"
// This doesn't generate an error either
m[1] = 2;
// This does generate an error, even though
// in javascript, m.foo means the same as
// m["foo"], so why does typescript treat
// them differently?
m.foo = "bar"
// This is what someone really should be
// doing to add an element to the map
m.set("baz", "qux")
The reason I use Typescript is usually because it prevents me from doing stupid things that the type does not support. However, in this case Typescript does not give an error. It doesn't seem to care that I'm trying to use square brackets to index into a map.
In fact, even for primitive data types like number it doesn't seem to mind me doing complete nonsense like this:
// Typescript allows you to index into any
// type, even a number?!??!?!
let x = 3;
let y = 4;
x["crazy"] = "yes";
// But again the behaviour is inconsistent
// between indexing with [] versus .
// The following is an error in Typescript.
x.crazy = "no"
Or even my own class.
class MyClass {
x: number;
}
let myInstance = new MyClass()
myInstance.x = 5;
myInstance["y"] = 10; // not an error
My questions are:
Upvotes: 5
Views: 1126
Reputation: 18993
The rationale of typescript allowing indexing is that the same semantic use of patterns for javascript has to be the same for typescript.
In this respect the property access o.property
and o['property']
have different expectations, see for example here
To add some more considerations, consider for example the javascript:
let x = 1
x["crazy"] = "yes"
x.pazzo = "no"
This may be transformed into valid typescript in this way:
declare let x: any;
x = 1
x["crazy"] = "yes";
x.pazzo = "no"
or in this way:
x = 1
x["crazy"] = "yes";
(<any>x).pazzo = "no"
x is declared/casted to have any shape, so x.pazzo
in this case become TS assignable.
The above behavoir make us assume that the primitive type number has an index signature [string]: any
: this imply that a number can be indexed in TS like in JS.
With noImplicitAny
option enabled the index signature [string]: any
is no more permitted for number:
error TS7017: Index signature of object type implicitly has an 'any' type.
Finally to answer to the final question set noImplicitAny: true
for enabling typescript to check for non indexable types.
Upvotes: 1
Reputation: 250386
With default compiler settings you can indeed index into objects you shouldn't index into. This was probably done to ease migration from JS to TS.
You can enable the compiler checks regarding indexing (an other implicit uses of any) using the noImplicitAny
flag, or more generally you can enable extra checks using the strict
flag.
Upvotes: 2