javascripttypescriptobjectcomputed-properties

Clarification on Computed Properties


I’m studying TypeScript and came across this pattern:

type Animal = { [key: string]: number };
 
let Tiger: Animal = { legs: 4, age: 5, tail: 1, eyes :2 };

From what I understand, this allows adding unlimited properties, as long as the key is a string and the value is a number.

My question is:

Is this approach considered idiomatic in TypeScript?

Would there be a better way to type known + unknown properties with more structure?


Solution

  • There's 2 types of object structures in general - dictionaries (maps) (properties with the same type) and objects (properties with different types). (Though we could have a map with different value types). Semantically I'd say you have an object, not a map. A map would be for example number of legs from different animals.

    I would not recommended to use such typing for an object. Loose typing like that have drawbacks like:

    1. You could make a type like lefs instead of legs
    2. You can't add additional props of different type like name: string

    I would use an interface which you can extends with additional properties for different animal types:

    interface Animal { 
      legs: number; 
      age: number, 
      tail: number, 
      eyes : number
    };
    
    interface Tiger extends Animal{
      color: 'stripes' | 'black'
    }
    
    let Tiger: Tiger = { legs: 4, age: 5, tail: 1, eyes :2 , color: 'stripes'};
    

    If your structure is rather a map you could improve by typing the keys thus prohibiting typos and non-existing keys:

    type Animal = Partial<Record<'legs'|'eyes'|'tail'|'age', number>>;