Skip to content
雲里
里雾

TypeScript const type parameter (5.0)

mindgym 开发 更新于 2026/4/23

TypeScript 5.0 引入的 const type parameter 让泛型函数的调用方无需手写 as const,函数定义侧即可要求编译器推导字面量类型(literal type)而非宽泛类型。


问题:泛型默认推导宽泛类型

function wrap<T>(value: T) { return value }

const result = wrap({ name: 'hello' })
// T 被推导为 { name: string },不是 { name: 'hello' }

如果我们需要字面量类型(比如要做类型级模板字符串解析),调用方必须加 as const

const result = wrap({ name: 'hello' } as const)
// T 被推导为 { readonly name: 'hello' }

这对库作者很痛苦——不能要求每个调用方都记得加 as const

解决:const type parameter

在泛型参数前加 const 关键字:

function wrap<const T>(value: T) { return value }

const result = wrap({ name: 'hello' })
// T 被推导为 { readonly name: 'hello' } — 自动!

编译器看到 const T 就会以字面量模式推导 T,等效于调用方写了 as const

MindGym 中的应用

i18n/types.tsdefineBundle() 使用 const type parameter,让 i18n bundle 的定义无需手写 as const satisfies Bundle

// 库侧定义
function defineBundle<const T extends { zh: Record<string, string>; en: Record<string, string> }>(
  bundle: T & StringsBundle<T['zh']>
): T { return bundle }

// 调用侧 — 无需 as const
export const schulteStrings = defineBundle({
  zh: { title: '舒尔特方格', instruction: '按 1 到 {{max}} 的顺序点击' },
  en: { title: 'Schulte Table', instruction: 'Click numbers 1 to {{max}} in order' },
})
// T 自动推导出字面量类型,ExtractParams 能解析 '{{max}}' 模板

没有 const Tinstruction 会被推导为 string,模板字面量类型 ExtractParamNames<string> 返回 never,插值功能失效。

限制

参见

参考