TypeScript无需泛型实现NonEmptyString非空字符串类型的方案
方案实现
目前TypeScript生态中最常用的无泛型通用非空字符串实现是 branded 类型 方案,类型定义本身不依赖泛型,同时支持编译时校验和运行时动态字符串校验,实现如下:
// 非空字符串类型定义,无任何泛型依赖 type NonEmptyString = string & { readonly __nonEmptyMarker: unique symbol } // 配套类型守卫函数,完成运行时校验 + 类型收窄,动态字符串场景必备 function isNonEmptyString(s: string): s is NonEmptyString { return s.length > 0 } // 可选:直接转换的工具函数,校验不通过抛出异常 function toNonEmptyString(s: string): NonEmptyString { if (!isNonEmptyString(s)) throw new TypeError("字符串不能为空") return s as NonEmptyString }
使用示例
declare function processStr(str: NonEmptyString): void // 处理动态字符串的场景:用户输入、接口返回等 const userInput = document.querySelector('input')?.value ?? "" if (isNonEmptyString(userInput)) { processStr(userInput) // 校验通过后编译正常 } // 固定值场景直接用工具函数转换 processStr(toNonEmptyString("正常内容"))
补充说明
你之前用到的固定前缀非空校验是利用了模板字面量的特性,但这个特性无法直接扩展到通用无前缀的场景:因为${string}本身包含空字符串,没有前缀的前提下无法通过模板字面量组合出排除空串的通用string子类型。
如果你的使用场景只需要校验字面量入参、不需要处理动态字符串,也可以选择在函数定义层面隐藏泛型,对外暴露无泛型的使用体验:
// 泛型仅在内部定义,使用者无需感知,也不需要单独定义泛型类型 declare function processStr<T extends string>(str: T extends "" ? never : T): void processStr("") // 编译直接报错 processStr("测试内容") // 编译正常
内容的提问来源于stack exchange,提问作者Wayne Van Son
相关产品推荐
相关产品推荐

