Home > Net >  Typescript: how to do type narrowing in an object mapper?
Typescript: how to do type narrowing in an object mapper?

Time:12-23

I have an object, where each value is a function that expects either a string, or array of strings:

const myMapper: Record<Filter, (value: string | string[]) => string> = {
  contains: (value: string) => `do something with ${value}`,
  between: ([value1, value2]: string[]) => `something with ${value1} and ${value2}`,
};

The problem: If I let ts know that the argument in the function can be either a string or an array, it will throw the error:

Type '(value: string) => string' is not assignable to type '(value: string | string[]) => string'

For the first item and a similar error for the second item.

How can I promise ts that I will know to pass the right type of value (string or array of strings) when using the object? Is the only option to use unknown for the second argument of Record?

CodePudding user response:

Simply omitting the explicit type annotation looks like it'd be enough, and is easier too.

const myMapper = {
  contains: (value: string) => `do something with ${value}`,
  between: ([value1, value2]: string[]) => `something with ${value1} and ${value2}`,
};

This way, you don't even need to "promise" that you'll pass the right type of argument - TypeScript will prevent you from passing the wrong argument in the first place contains will only accept a string, and between will only accept an array of strings).

  • Related