You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 22:36:26