Home > Enterprise >  How to dynamically use a string value as key type in return object in order to have proper typings?
How to dynamically use a string value as key type in return object in order to have proper typings?

Time:10-10

I have a higher order function that will inject a key / value into an object and return it.

import { v4 as uuid } from 'uuid';

const withPrimaryKey = (key: string) => <T>(input: T) => {
    return {
        ...input,
        [key]: uuid()
    }
}

export default withPrimaryKey;

In usage, it would look like this:

const injectPrimaryKey = withPrimaryKey('categoryId');

const input = {
  name: 'books'
};

const data = injectPrimaryKey(input);

console.log(data); // { categoryId: '25b9dea6-5856-4c53-bfef-c2505eacae15', name: 'books' }

As is, it works fine.. however the typings of the returned data object does not indicate that categoryId exists. And doing the following throws a Typescript error:

const data: typeof input & { categoryId: string } = insertPrimaryKey(input);

Property 'categoryId' is missing in type [...]

How do I properly type my withPrimaryKey function in order to dynamically include categoryId and if that is not possible, what's the next best thing?

CodePudding user response:

You could change key type to generic and use type assertion for return value (without type assertion K is widened to string):

const withPrimaryKey = <K extends string>(key: K) => <T>(input: T) => {
    return {
        [key]: uuid(),
        ...input,
    } as Record<K, string> & T
}

Playground

  • Related