DEV Community

Cover image for Dependent Function Arguments With TypeScript
Daniel Bellmas
Daniel Bellmas

Posted on • Updated on

Dependent Function Arguments With TypeScript

Typescript is an excellent tool for making sure we have fewer bugs by having the IDE complete our code in accordance with the types we defined.

Here we'll see how to use mapped types to have more control over our functions while making them more readable for the next developer that uses those functions.

const enum DATA_TYPE {
  STYLE = 'STYLE',
  THEME = 'THEME'
}

const enum STYLE_PROPERTY {
  ID = 'ID',
  NAME = 'NAME',
  DATE = 'DATE'
}

const enum THEME_PROPERTY {
  ID = 'ID',
  NAME = 'NAME',
  LAST_MODIFIED = 'LAST_MODIFIED',
  ORIGIN_THEME = 'ORIGIN_THEME',
  PROTECTED = 'PROTECTED'
}

interface ListGetTypeMap {
  [DATA_TYPE.STYLE]: STYLE_PROPERTY[];
  [DATA_TYPE.THEME]: THEME_PROPERTY[];
}

interface ObjectGetTypeMap {
  [DATA_TYPE.STYLE]: {
    [STYLE_PROPERTY.ID]?: string;
    [STYLE_PROPERTY.NAME]?: string;
    [STYLE_PROPERTY.DATE]?: string;
  };
  [DATA_TYPE.THEME]: {
    [THEME_PROPERTY.ID]?: string;
    [THEME_PROPERTY.NAME]?: string;
    [THEME_PROPERTY.LAST_MODIFIED]?: string;
    [THEME_PROPERTY.ORIGIN_THEME]?: string;
    [THEME_PROPERTY.PROTECTED]?: boolean;
  };
}

type TGetProperty = <T extends keyof ListGetTypeMap>(type: T, keys: ListGetTypeMap[T]) => ObjectGetTypeMap[T];
Enter fullscreen mode Exit fullscreen mode

Try it out in this Typescript Playground 🎈


Code Breakdown

Our goal here is to make sure the developer that uses a function of type TGetProperty, will have Typescript guard the arguments he gives that function.

In our case, we want to make sure that every item in the keys array is either of type STYLE_PROPERTY[] or THEME_PROPERTY[].
By defining the type argument as DATA_TYPE.STYLE or DATA_TYPE.THEME
we get the type of the keys argument.

This is a scalable solution

If we want to add another enum like CONTENT_PROPERTY for example, all we need to do is add it to ListGetTypeMap and ObjectGetTypeMap; and we have support for it too πŸŽ‡

Let's see some examples

Say func1 is a function that is of type TGetProperty.

Bad examples β›”

First bad example

When passing DATA_TYPE.STYLE to the type argument, Typescript expects the next argument to be of type STYLE_PROPERTY only,
and the error message is pretty clear too so that's cool πŸ†’

Second bad example

Same here, passing DATA_TYPE.THEME to type will make Typescript reject an array with items of type STYLE_PROPERTY, and only accept items of type THEME_PROPERTY.

Good examples βœ…

Good examples


Conclusion

Use Typescript to help set guards and guidelines for the next developer that will use the functions you wrote.
This will result in fewer bugs and overall more productive coding.

Top comments (0)