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

如何让not工具函数实现!操作符的Type narrowing类型收窄效果?

如何让自定义not函数具备TypeScript类型收窄能力?

问题场景

我编写了用于判断输入是否为有效字符串的类型守卫函数及not工具函数:

export function isString(v: unknown): v is string {
   return typeof v === "string";
}

export function not(v) {
   return v === false;
}

在main函数中,我希望通过not做无效输入的提前返回,但遇到了类型收窄问题:

function main(input?: string) {
  if(not(isString(input))) {
     return
  }

  // 错误:此处无法将input识别为string类型
  processString(input);
}

function processString(input: string) {
   // ...
}

直接使用!操作符(if(!isString(input)))可以正常实现类型收窄,但我更倾向于not这种可读性更高的语法,想问能否配置not函数,让它具备和!相同的类型收窄能力?

解决方案

可以通过给not函数添加泛型类型谓词重载,让TypeScript识别其反向类型收窄逻辑。

修改后的not函数定义如下:

// 针对类型守卫的重载:反转类型判断结果
export function not<T>(v: v is T): v is not T;
// 针对普通布尔值的重载
export function not(v: boolean): boolean;
// 实现逻辑
export function not(v: unknown): boolean {
   return v === false;
}

这样当你调用not(isString(input))时,TypeScript会理解:如果这个表达式返回true,则input is not string,因此在return之后的代码块中,input会被正确收窄为string类型,processString(input)就能正常通过类型检查。

如果需要支持更通用的类型守卫函数(比如接收参数的守卫),可以用更灵活的泛型定义:

type NegateGuard<T extends (x: any) => x is any> = 
  T extends (x: infer U) => x is infer V ? (x: U) => x is Exclude<U, V> : never;

// 接收类型守卫函数并返回反向守卫
export function not<T extends (x: any) => x is any>(guard: T): NegateGuard<T>;
// 接收布尔值取反
export function not(v: boolean): boolean;

export function not(v: unknown): unknown {
  if (typeof v === 'function') {
    return (x: unknown) => !v(x);
  }
  return !v;
}

这种写法可以支持类似not(isString)这样直接传递守卫函数的场景,进一步提升代码灵活性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 22:02:54