Home > Enterprise >  Typescript map object type to strongly typed array
Typescript map object type to strongly typed array

Time:03-09

I have an object type which I want to map to a strongly typed key, value array.

This is what I came up with so far:

export interface StepWidgetItem<T, V> {
    key: T;
    value: V;
}

interface UseStepWidgetsContainer<T extends object> {
    data: T;
}

interface UseStepWidgetsContainerProps<T extends object> {
    items: StepWidgetItem<keyof T, T[keyof T]>[];
}

export const useStepWidgetsContainer = <T extends object>({
    items,
}: UseStepWidgetsContainerProps<T>): UseStepWidgetsContainer<T> => {
    const data = {} as T;

    console.log(items);

    return {
        data,
    };
};

The problem i when I call it like this:

interface Data {
    test: string;
    test2: number;
}

useStepWidgetsContainer<Data>({
    items: [
        {
            key: 'test',
            value: 'test',
        },
        {
            key: 'test2',
            value: 'test', // should be an error, but string is currently allowed...
        },
        {
            key: 'test2',
            value: 1,
        },
    ],
});

The value of array item with key: 'test2' must be a number, but currently it may be any type of the values of Data, so string|number.

Is it possible to force a number when key === 'test2'?

CodePudding user response:

You are very close The problem is that StepWidgetItem<keyof T, T[keyof T]> will mix any key of T with any value in T.

The solution is to first associate the key with the value creating a type for each property, for ex: StepWidgetItem<"test", string> StepWidgetItem<"test2", number>. We can do this using a mapped type to first create for each property, the associated StepWidgetItem and then index into the mapped type using [keyof T] to get a union of all StepWidgetItem types we just created.

interface UseStepWidgetsContainerProps<T extends object> {
    items: Array<{
      [P in keyof T]: StepWidgetItem<P, T[P]>
    }[keyof T]>
}

Playground Link

  • Related