DEV Community

Marco
Marco

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

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

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 • 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

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more

Best practices for optimal infrastructure performance with Magento

Running a Magento store? Struggling with performance bottlenecks? Join us and get actionable insights and real-world strategies to keep your store fast and reliable.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️