Typescript 将对象类型映射到强类型数组

Typescript map object type to strongly typed array

我有一个对象类型,我想将其映射到强类型键、值数组。

这是我到目前为止想出的:

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,
    };
};

当我这样称呼它时遇到的问题:

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,
        },
    ],
});

array item with key: 'test2' 的值必须是一个数字,但目前它可以是Data的任何类型的值,所以string|number.

当键===时是否可以强制输入数字'test2'?

你非常接近问题是 StepWidgetItem<keyof T, T[keyof T]> 会将 T 的任何键与 T 中的任何值混合。

解决方案是首先将键与值关联起来,为每个 属性 创建一个类型,例如:StepWidgetItem<"test", string> StepWidgetItem<"test2", number>。我们可以使用映射类型来执行此操作,首先为每个 属性 创建关联的 StepWidgetItem,然后使用 [keyof T] 索引映射类型以获得我们刚刚创建的所有 StepWidgetItem 类型的联合.

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

Playground Link