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

如何让TypeScript非空类型收窄实现更优雅?

优化TypeScript非null/undefined类型收窄的优雅方案

你希望通过类型守卫实现对非null/undefined变量的公共方法(如toString、constructor等)的安全访问,当前直接用o !== null && o !== undefined无法让TypeScript自动收窄类型,但自定义类型守卫可以解决问题。以下是几种更优雅的优化方案:

核心问题说明

TypeScript对unknown类型的收窄逻辑严格:即使排除了null和undefined,剩余类型仍为unknown,TS无法确认它具备公共对象方法,因此禁止直接访问属性。自定义类型守卫通过显式声明类型范围,填补了TS类型系统与JS运行时行为的差异。

优化方案1:简化自定义类型守卫

将类型定义和守卫函数写得更紧凑清晰:

// 明确覆盖所有非null/undefined且拥有公共对象方法的类型
export type Something = string | number | boolean | symbol | bigint | object;

// 简洁箭头函数形式的类型守卫
export const isSomething = (val: unknown): val is Something => 
  val !== null && val !== undefined;

function Narrowing(o: unknown) {
    if (isSomething(o)) {
      console.log(o.toString(), o.constructor);
    }
}

优化方案2:复用内置类型(可选)

如果想利用TS内置的NonNullable类型,可以结合条件类型明确范围,这种写法适合追求类型复用的场景:

// 从NonNullable<unknown>中筛选出具备公共方法的类型
export type Something = NonNullable<unknown> extends infer T 
  ? T extends string | number | boolean | symbol | bigint | object ? T : never 
  : never;

export const isSomething = (val: unknown): val is Something => 
  val !== null && val !== undefined;

优化方案3:直接使用类型断言(不推荐)

如果不想额外定义类型守卫,可在判断后添加类型断言,这种写法更简洁但丢失了类型守卫的“运行时-类型系统”关联,仅适合简单场景:

function NotNarrowing(o: unknown) {
    if (o !== null && o !== undefined) {
      const safeObj = o as string | number | boolean | symbol | bigint | object;
      console.log(safeObj.toString(), safeObj.constructor);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:43:26