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

Typescript 函数扩展对象如何自动保留const字面量类型无需用户手动声明

实现方案

你要的效果完全可以实现,针对不同TypeScript版本有两种成熟写法:

适配TypeScript 5.0及以上版本

使用TS 5.0新增的const类型参数特性,直接给泛型添加const修饰符,即可让TS自动按字面量类型推导传入的参数,无需用户手动加as const:

const DEFAULT_COLORS = { WHITE: '#fff' } as const

// 仅在泛型前加const修饰即可
const extendColors = <const T extends Record<string, string>>(newColors: T) => {
  return { ...DEFAULT_COLORS, ...newColors } as const
}

// 调用示例,无额外语法
const colors = extendColors({ RED: '#FF0000' })
// 推导结果:
// colors.WHITE 的类型是字面量 "#fff"
// colors.RED 的类型是字面量 "#FF0000"
// 输入colors.时会自动提示所有键,访问不存在的键会报类型错误

兼容TypeScript 5.0以下版本

如果你的组件库需要兼容更低版本的TS,可以通过拆分泛型约束的方式实现同样的效果:

const DEFAULT_COLORS = { WHITE: '#fff' } as const

// 把值类型单独抽为泛型S约束为string,强制TS保留字面量
const extendColors = <T extends Record<string, S>, S extends string>(newColors: T) => {
  return { ...DEFAULT_COLORS, ...newColors } as const
}

// 调用方式完全一致
const colors = extendColors({ RED: '#FF0000' })

原理解释

你之前的写法推导失效,是因为TS默认推导可变对象参数时,会把字符串属性值拓宽为string类型,避免后续修改属性值时报错。

  • 加const泛型修饰符后,TS会默认将传入的对象视为不可变的,和手动加as const的推导效果完全一致
  • 低版本的拆分泛型写法,是通过单独约束值类型为string的子类型,强制TS不把字面量拓宽为通用string类型

内容的提问来源于stack exchange,提问作者User

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:45:04