DEV Community

Marco A.
Marco A.

Posted on

How-to: Use dictionary in TypeScript

Here is the scenario, I want to create a function getLegsNumber that use this structure as dictionary

const mappingAnimalLegs = {
    'CAT' : 4,
    'DOG' : 4,
    'DUCK' : 2
}
Enter fullscreen mode Exit fullscreen mode

If I write something like this

function getLegsNumber(animal) {
    return mappingAnimalLegs[animal] | 0
}
Enter fullscreen mode Exit fullscreen mode

Typescript is not happy and tell us:


Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ CAT: number; DOG: number; DUCK: number; }'.(7053)

So... how I can solve this without adding too much noise ?

Here is my solution:

function getLegsNumber(animal: string): number {
  if (animal in mappingAnimalLegs) {
    return mappingAnimalLegs[animal as keyof typeof mappingAnimalLegs];
  }
  return 0
}
Enter fullscreen mode Exit fullscreen mode

I can also simplify a bit more with

function getLegsNumber(animal: string): number {
    return mappingAnimalLegs[animal as keyof typeof mappingAnimalLegs] | 0
}
Enter fullscreen mode Exit fullscreen mode

What do you think?

Typescript playground as reference

Top comments (3)

Collapse
 
sylvaindethier profile image
Sylvain Dethier

Well you almost get it ! I suggest to be more specific on the types, to prevent dumb errors and to get autocompletion:

// Dictionary with predefined typed keys
type Dictionary = Record<"CAT" | "DOG" | "DUCK", number>;

const mappingAnimalLegs: Dictionary = {
    'CAT' : 4,
    'DOG' : 4,
    'DUCK' : 2
};

function getLegsNumber(animal: keyof Dictionary): number {
    return mappingAnimalLegs[animal] | 0;
}

getLegsNumber("foo"); // <-- TS error
getLegsNumber("CAT");
Enter fullscreen mode Exit fullscreen mode

See this TS Playground

The point is to NOT make type assertion by using the as keyword which is considered a bad practice, use it only when there's no other choice.

Collapse
 
linediconsine profile image
Marco A. • Edited

Thanks!!

I would like to avoid this

// Dictionary with predefined typed keys
type Dictionary = Record<"CAT" | "DOG" | "DUCK", number>;
Enter fullscreen mode Exit fullscreen mode

I don't like the repetition, any suggestion?

--EDIT--
Using your idea, I can update the code to:
(note: I removed the |0 for now)

const mappingAnimalLegs = {
    'CAT' : 4,
    'DOG' : 4,
    'DUCK' : 2
}

function getLegsNumber(animal: keyof typeof mappingAnimalLegs): number {
    return mappingAnimalLegs[animal]
}

getLegsNumber('CAT')
getLegsNumber('foo')
Enter fullscreen mode Exit fullscreen mode

Playground

Collapse
 
sylvaindethier profile image
Sylvain Dethier

Yes it's good. It's preferable to also type variables (const, let, - avoid var)

const mappingAnimalLegs: Record<string, number> = {
  // the map
}
Enter fullscreen mode Exit fullscreen mode

The important point is the function parameter type animal: keyof typeof mappingAnimalLegs so that you get autocompletion & type error early
Also be careful, it might seems you've done a typo error: getLegsNamber --> getLegsNumber