TypeScript联合类型字符串插值为何生成冗余联合?如何优化?
问题分析与解决
先看这段代码:
export const schedules = [ { unit: "hour", quantity: 6 }, { unit: "day", quantity: 1 }, ] as const; const getScheduleName = (schedule: (typeof schedules)[number]) => `${schedule.quantity}_${schedule.unit}` as const
以及对应的类型定义:
type Schedule< T extends (typeof schedules)[number] = (typeof schedules)[number], > = `${T["quantity"]}_${T["unit"]}`
为什么会生成非预期的联合类型?
(typeof schedules)[number]对应的是联合类型:{ readonly unit: "hour"; readonly quantity: 6; } | { readonly unit: "day"; readonly quantity: 1; }。但TypeScript处理模板字符串类型或函数返回值时,会将联合类型的属性独立展开——它不会保留quantity:6与unit:"hour"、quantity:1与unit:"day"的绑定关系,而是把所有quantity值和所有unit值交叉组合,最终生成了"6_hour" | "6_day" | "1_hour" | "1_day"。
如何让类型推导精准匹配原配对?
方法一:拆分常量定义,保留属性关联
把数组内的每个对象单独定义为const常量,让每个对象的类型独立且属性绑定,这样联合类型的每个成员都会保持自身属性的关联关系:
const hourlySchedule = { unit: "hour", quantity: 6 } as const; const dailySchedule = { unit: "day", quantity: 1 } as const; export const schedules = [hourlySchedule, dailySchedule] as const; // 返回类型自动推导为 "6_hour" | "1_day" const getScheduleName = (schedule: (typeof schedules)[number]) => `${schedule.quantity}_${schedule.unit}` as const; // 直接复用函数返回类型即可 type Schedule = ReturnType<typeof getScheduleName>;
方法二:用条件类型提取单个对象的属性关联
通过infer关键字在条件类型中提取单个对象的unit和quantity,确保两者来自同一个对象实例,避免交叉组合:
export const schedules = [ { unit: "hour", quantity: 6 }, { unit: "day", quantity: 1 }, ] as const; // 遍历数组元素,提取每个元素的属性并组合 type Schedule = typeof schedules[number] extends infer SingleItem ? SingleItem extends { unit: infer U; quantity: infer Q } ? `${Q & number}_${U & string}` : never : never; // 函数通过泛型约束,确保返回值和输入参数的属性绑定 const getScheduleName = <T extends typeof schedules[number]>(schedule: T) => `${schedule.quantity}_${schedule.unit}` as `${T["quantity"]}_${T["unit"]}`;
内容的提问来源于stack exchange,提问作者user3781458
相关产品推荐
相关产品推荐

