类型判断函数库需兼顾一致性、可扩展性与可读性,应基于 Object.prototype.toString.call 统一获取类型标签,分层提供 isType/isLike/isValid 判断,支持 TypeScript 类型守卫,并显式配置规则以保障可维护性。

类型判断函数库要真正可维护,核心在于一致性、可扩展性、可读性三者兼顾——不是堆砌 instanceof 或 constructor,而是建立清晰的判定契约和统一的抽象层。
用 Symbol.toStringTag 统一基础类型识别
JavaScript 原生 toString() 返回 "[object Type]",但自定义类可能未设置 Symbol.toStringTag,导致判断失准。应优先基于 Object.prototype.toString.call(value) 获取标准标签,再映射为语义化类型名:
- 对 null、undefined 单独处理(toString 返回 "[object Null]" 和 "[object Undefined]",但语义上需直白返回 "null" / "undefined")
- 将 "[object Array]" → "array"、"[object Promise]" → "promise"、"[object Map]" → "map" 等标准化为小写英文标识
- 暴露底层
getTag(value)方法,方便用户扩展或调试,避免黑盒逻辑
区分“类型”与“形状”,提供分层判断能力
一个值是 Array,不等于它“可用作数组”;一个对象有 length 属性,也不代表它是类数组。库应明确划分判断层级:
- isType:严格对应语言规范类型(如 isString、isNumber、isFunction),基于 toStringTag + 特殊值(NaN、+0/-0)精细处理
- isLike:关注行为契约(如 isLikeArray 检查是否有 length 和数字索引;isLikePromise 检查 then 是否为函数)
- isValid:业务相关校验(如 isNonEmptyString、isPositiveInteger),应允许用户注册自定义谓词,而非硬编码
支持类型守卫(Type Guard)并兼容 TypeScript
函数不仅要返回 boolean,还要能参与 TypeScript 类型收窄。每个导出的判断函数都应带类型断言签名:
- 例如
function isArray<t>(value: unknown): value is Array<t></t></t>,让 if (isArray(x)) { x.push(...) } 获得正确类型推导 - 对联合类型(如 isPlainObject)使用泛型约束,避免 any 泄漏
- 提供 .d.ts 文件,类型定义与运行时逻辑严格对齐,不靠 JSDoc “骗”类型系统
拒绝魔数与隐式依赖,所有规则显式可配置
避免在内部硬编码 Date 构造函数名或 RegExp 字面量来识别类型。所有判定逻辑应:
- 把内置构造器(Date、RegExp、Error 等)作为参数注入,便于测试替换或适配非标准环境(如某些打包器重写全局)
- 将正则匹配、属性检查等规则提取为常量或配置项,比如
ARRAY_LIKE_KEYS = ['length'] - 导出判定规则表(如
typeRules: Record<string unknown> boolean></string>),支持运行时增删改
不复杂但容易忽略:每次新增一个 isXxx 函数,同步更新类型定义、单元测试、文档示例,并确保它不破坏已有判定的边界条件(比如 isObject(false) 必须为 false)。

















