1
votes

In JavaScript, plain old objects can take all kinds of abuse. For example you can write:

var obj = {};
var func = new Function() {};
obj[func] = 5; // totally fine
obj[func]; // returns 5

With some creativity you could write a generic class SimpleSet<T> that might use an object as its backing store in JavaScript or TypeScript. One straightforward way may involve writing something like this:

public add(val: T) {
  this._dict[val] = val;
}

Which doesn't work in TypeScript. Why? More permissive versions of add work, see add2 and add3.

class SimpleSet<T> {
  _dict: Object;
  constructor() {

  }

  // error:
  public add(val: T) {
    this._dict[val] = val;
  }

  // no error:    
  public add2(val: T) {
    this._dict[val as any] = val;
  }

  // no error:
  public add3(val: any) {
    this._dict[val] = val;
  }
}

With add, two errors appear:

Type 'T' is not assignable to type 'Object[T]'.

Type 'T' cannot be used to index type 'Object'.

enter image description here

Why?

1
Your function creation syntax is wrong, but do you realize setting a function as the key to a JS object will cast the function to a string, creating a key something like this: "function (){}"?Alexander O'Mara
var obj = {}; var key1 = {prop1:'val1'}; var key2 = {prop2:'val2'}; obj[key1] = "hello"; console.log(Object.keys(obj)); will log ["[object Object]"]. Logging obj[key2] will show "hello" because the toString() of both objects are the same.Heretic Monkey
You've gotten pretty far on something that doesn't work...Ryan Cavanaugh
I wasn't trying to make a workable set here (this would be insane in JS too), but trying to figure out the rule for any being allowed vs Object being disallowed as a type. I see now I was under the mistaken belief that any means "allow all types", instead of "opt out of type checking."Simon Sarris

1 Answers

5
votes

TypeScript doesn't let you because it doesn't work, which is a pretty decent reason as far as things go.

The indexing keys of JavaScript objects are always (always) strings. Indexing by other sorts of things coerces the key to a string and then looks up by that. For example, as pointed out in comments, indexing by an object produces the key "[object Object]"

You can use the ES6 Map object for a working object-to-value store.