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

TypeScript插值模板字符串在判别联合中类型推断异常是否为Bug?

TypeScript判别联合类型中的模板字符串类型推断问题

问题描述

当在判别联合类型中使用包含undefined的插值模板字符串(如{ href: #234${undefined}2213 })时,TypeScript出现异常行为:

  • 该模板字符串未被正确识别为string类型,导致联合类型的判别逻辑失效
  • 对应实例中onClick回调的ev参数丢失类型推断,变为any,但普通字符串或无href的情况下类型推断正常

复现代码如下:

type BiomePlainLinkProps = {
  href: string;
  onClick?: (event: string) => void;
}

type BiomeButtonProps = {
  href?: never;
  onClick?: (event: number) => void;
}

export type ClickableDiscriminatedUnion =
  | BiomePlainLinkProps
  | BiomeButtonProps;

const p1: ClickableDiscriminatedUnion = {
  href: '2332132',
  onClick: (ev) => console.log('@@@@', ev), // ev 类型为 string
}

const p2: ClickableDiscriminatedUnion = {
  onClick: (ev) => console.log('@@@@', ev), // ev 类型为 number
}

const p3: ClickableDiscriminatedUnion = {
  href: `2${undefined}332132`,
  onClick: (ev) => console.log('@@@@', ev), // ev 类型为 any(预期为 string)
}

原因分析

  1. 模板字符串的类型推断规则:当模板字符串中插入undefined时,TypeScript会将其推断为string | undefined类型,而非单纯的string。这是因为静态类型检查会考虑插值表达式的原始类型,即使运行时${undefined}会被转为字符串"undefined",类型系统仍会拓宽模板字符串的类型范围。
  2. 联合类型判别失效:由于href的类型变为string | undefined,既不匹配BiomePlainLinkProps中href: string的严格要求,也不满足BiomeButtonProps中href?: never的约束,TypeScript无法确定当前实例属于联合类型的哪个分支,因此无法正确推断onClick回调的参数类型,最终退化为any。

解决方案

方案1:显式断言模板字符串为string

通过类型断言明确指定模板字符串的类型,帮助TypeScript识别联合类型分支:

const p3: ClickableDiscriminatedUnion = {
  href: `2${undefined}332132` as string,
  onClick: (ev) => console.log('@@@@', ev), // ev 类型为 string
}

方案2:显式转换undefined为字符串

在插值时将undefined转为字符串,确保模板字符串被推断为string类型:

const p3: ClickableDiscriminatedUnion = {
  href: `2${String(undefined)}332132`,
  onClick: (ev) => console.log('@@@@', ev), // ev 类型为 string
}

方案3:调整联合类型定义(谨慎使用)

如果业务场景允许,可以放宽BiomePlainLinkProps的href约束,但会模糊联合类型的判别逻辑:

type BiomePlainLinkProps = {
  href?: string;
  onClick?: (event: string) => void;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:07:28