为什么typescript不能为泛型函数推断类型?

pn9klfpd  于 2023-06-24  发布在  TypeScript
关注(0)|答案(1)|浏览(153)

我尝试键入function,以便能够推断出正确的键:

type GroupedObject<T extends Record<string, string>> = {
  [K in keyof T & string as T[K] extends `${infer Group}-${infer Rest}` ? Group : never]: {
    [Key in keyof T as T[Key] extends `${K}-${infer Rest}` ? Key : never]: T[Key]
  }
}

export function groupObjectByPattern<T extends Record<string, string>>(obj: T): GroupedObject<T> {
  const groupedObject: GroupedObject<T> = {} as GroupedObject<T>

  for (const key in obj) {
    const [group] = key.split('-')

    if (!groupedObject[group]) {
      groupedObject[group] = {} as Pick<T, Extract<keyof T, `${string}-${string}`>>
    }

    groupedObject[group][key] = obj[key]
  }

  return groupedObject
}

通过这样做,我应该能够实现正确的推理。例如:

const inputObject = {
  "color-background-primary": "#ffffff",
  "color-background-secondary": "#f3f4f4",
  "color-background-tertiary": "#e4e7e7",
  "color-background-interactive": "#0b968f",
  "color-background-hover": "#026661",
  "color-background-active": "#2079c3",
  "font-primary": "foo",
  "space-xs": "xs",
};

const groupedObject = groupObjectByPattern(inputObject);
groupedObject.color; // { "color-background-primary": string; "color-background-secondary": string; "color-background-tertiary": string; "color-background-interactive": string; "color-background-hover": string; "color-background-active": string; }

但我没有得到任何情报。我做错了什么?任何帮助将不胜感激。

knsnq2tg

knsnq2tg1#

您在应该选中K的位置选中了T[K]
第二个检查应该是${Group}-${infer Rest},这在代码中是不可能的,因为它在三进制中丢失了。

type Split1<S extends string> = S extends `${infer F}-${string}` ? F : S;
type GroupedObject2<T> = {
  [K in Split1<keyof T & string>]: {
    [P in keyof T as P extends `${K}-${infer E}` ? E : never]: T[P]
  }
}
type Q = GroupedObject2<typeof inputObject>
//   ^?
// type Q = {
//     color: {
//         "background-primary": string;
//         "background-secondary": string;
//         "background-tertiary": string;
//         "background-interactive": string;
//         "background-hover": string;
//         "background-active": string;
//     };
//     font: {
//         ...;
//     };
//     space: {
//         ...;
//     };
// }

如果你不想拆分子键,那就更容易了

type GroupedObject3<T> = {
  //                       inlined Pick<T, Extract<keyof T, `${K}-${string}`>>
  [K in Split1<keyof T & string>]: { [P in keyof T & `${K}-${string}`]: T[P]; }
}
type W = GroupedObject3<typeof inputObject>
//   ^?
// type W = {
//     color: {
//         "color-background-primary": string;
//         "color-background-secondary": string;
//         "color-background-tertiary": string;
//         "color-background-interactive": string;
//         "color-background-hover": string;
//         "color-background-active": string;
//     };
//     font: {
//         ...;
//     };
//     space: {
//         ...;
//     };
// }

相关问题