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

如何为字符串模板字面量创建类型守卫并区分联合类型?

区分TypeScript模板字面量联合类型的正确方式

问题背景

当定义Url = https://${string}或`ID = `${string}_id这类模板字面量联合类型后,直接使用startsWith或includes等运行时字符串检查无法让TypeScript自动收窄类型,导致传入对应类型的函数时出现类型不兼容错误。

解决方案:自定义类型守卫函数

TypeScript无法自动将普通字符串操作与模板字面量类型关联,需要手动编写类型守卫函数,明确告诉编译器运行时检查通过后变量的具体类型。

定义类型守卫

为每个模板字面量类型编写返回val is [Type]的守卫函数:

function isUrl(val: string): val is Url {
  return val.startsWith("https://");
}

function isID(val: string): val is ID {
  return val.endsWith("_id");
}

修正后的完整代码

type Url = `https://${string}`;
type ID = `${string}_id`;
type AttributeType = number | Date | Url | ID;

const handleNumber = (val: number) => console.log(`${val}: is a number!`)
const handleDate = (val: Date) => console.log(`${val}: is a date!`)
const handleUrl = (val: Url) => console.log(`${val}: is a url!`)
const handleID = (val: ID) => console.log(`${val}: is an id!`)

// 自定义类型守卫函数
function isUrl(val: string): val is Url {
  return val.startsWith("https://");
}

function isID(val: string): val is ID {
  return val.endsWith("_id");
}

function AttributeLabel(attribute: AttributeType) {
  if (typeof attribute === "number") {
    handleNumber(attribute);
  } 
  else if (attribute instanceof Date) {
    handleDate(attribute);
  }
  else if (typeof attribute === "string" && isUrl(attribute)) {
    handleUrl(attribute); // 类型成功收窄为Url,无报错
  } 
  else if (typeof attribute === "string" && isID(attribute)) {
    handleID(attribute); // 类型成功收窄为ID,无报错
  }
};

// 测试输出
console.log(AttributeLabel(1)) // 1 is a number!
console.log(AttributeLabel(new Date())) // [当前日期] is a date!
console.log(AttributeLabel("https://google.com")) // https://google.com is a url!
console.log(AttributeLabel("dog_id")) // dog_id is an id! 

原理说明

类型守卫函数通过返回val is Type的类型谓词,让TypeScript编译器知道:当函数返回true时,变量val的类型就是指定的模板字面量类型。这就把运行时的字符串检查和编译时的类型推断关联起来,实现了准确的类型收窄。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:22:47