Describe the shape of an object

INPUT · Slides

When you do not know the names of the keys

01 / 06

When you cannot line the property names up

Every object type so far has been written by lining up the property names in advancename, age, and so on. For data whose contents are settled, like a person or a product, that is right.

But what about data like "a score per person"? The keys are people’s names, and what the keys will be is not knowable until it runs. You cannot line them up one by one.

02 / 06

[key: string] where the name goes

When that happens, write [key: string] where the property name would go. It means "the key is some string or other, and every value is a number".

The key part can be any name you like. It is there to tell the reader "what goes here is a key".

type Scores = {  [key: string]: number;};const scores: Scores = {  yui: 80,  rin: 70,};console.log(scores.yui);

Result

80

03 / 06

When the key is in a variable, use []

You can take it out with ., as in scores.yui, but when the key is in a variable . will not do. Instead you put the variable inside [].

scores[k] means "the value under the string that is in k". If you are handling data whose keys are not settled, this is the one you will use most.

type Scores = {  [key: string]: number;};const scores: Scores = { yui: 80 };const k: string = "yui";console.log(scores[k]);

Result

80

04 / 06

Go round them all with Object.keys

When you want to know every key that is in there, use Object.keys. Hand it an object and you get back an array of the keys. After that it is the for...of you have just learnt, one at a time.

There are other ways to go round an object, but with Object.keys you can read it as "going round an array". Use this one.

type Scores = {  [key: string]: number;};const scores: Scores = {  yui: 80,  rin: 70,};for (const k of Object.keys(scores)) {  console.log(k + ":" + scores[k]);}

Result

yui:80
rin:70

05 / 06

Reading a key that is not there does not stop you

Here is the trap. An index type says "the key can be anything", so writing a key that is not in there is not an error.

As far as the type goes you think it is a number, but what actually comes back is undefined. Mistype a name and nothing tells you on the spot. Get into the habit of checking with !== undefined before you use it.

type Scores = {  [key: string]: number;};const scores: Scores = { yui: 80 };console.log(scores["rin"]);

Result

undefined

06 / 06

If the keys are settled, line the properties up

It looks handy, but the important thing is not to overuse it.

  • If the names of the keys are settled in advance, a type that lines them up one by one, name: string;, is better. Typos get caught on the spot
  • Only use an index type when the keys are not knowable until it runs

Remember that you are trading the check on names for the ease of writing. Let us write some.