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

TypeScript中如何让自定义标签模板函数返回对应字符串字面量类型

问题核心原因

默认情况下TypeScript会将模板标签函数接收的TemplateStringsArray内的字符串元素类型宽化为string,不会保留原始的字面量类型,所以直接对TemplateStringsArray做泛型约束无法拿到精确的字面量类型。


解法1:适配无插值场景(兼容TS 4.x及以上版本)

通过元组类型强制捕获字符串的字面量类型,再和TemplateStringsArray交叉,既符合类型定义又能保留字面量信息:

function taggedLiteral<T extends string>(strings: [T, ...string[]] & TemplateStringsArray): T {
  return strings[0]
}

const test: 'foobar' = taggedLiteral`foobar` // 无报错,test类型自动推导为"foobar"

解法2:适配带插值场景(TS 5.0+可用)

配合TS 5.0引入的const类型参数,递归拼接模板字符串和插值的类型,实现完整字面量返回:

// 递归拼接模板字符串与插值的类型
type JoinTemplate<S extends readonly string[], V extends readonly unknown[]> =
  S extends [infer First extends string, ...infer RestS extends readonly string[]]
    ? V extends [infer FirstV, ...infer RestV extends readonly unknown[]]
      ? `${First}${FirstV}${JoinTemplate<RestS, RestV>}`
      : First
    : ""

function taggedLiteral<const S extends readonly string[], const V extends readonly unknown[]>(
  strings: S & TemplateStringsArray,
  ...values: V
): JoinTemplate<S, V> {
  return String.raw(strings, ...values) as never
}

// 测试无插值
const test1 = taggedLiteral`foobar` // 类型推导为"foobar"
// 测试带插值
const num = 123
const str = "test"
const test2 = taggedLiteral`foo${num}bar${str}` // 类型推导为"foo123bartest"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:54:03