Typescript中如何判断对象类型的原型是Object.prototype
结论
TypeScript 类型系统没有暴露原型链相关的元信息,无法100%准确判断一个类型的原型是否严格等于Object.prototype,但可以通过调整条件分支顺序、提前排除非普通对象类型的方式,解决你当前遇到的问题,覆盖绝大多数业务场景。
问题原因
你现有实现的问题在于T extends Partial<Record<string, any>>的匹配范围过宽:函数、类实例、Set/Map等所有对象类型都可以匹配该分支,所以函数类型没有被正确识别返回。
修复方案
首先在匹配普通对象分支前,提前排除所有不需要递归的非普通对象类型,首当其冲就是先匹配函数类型:
// 你需要先定义基础原始类型,根据业务需求调整范围 type Primitive = string | number | boolean | null | undefined | symbol | bigint; type MapDeep<T> = F< T extends Primitive ? T : T extends Array<infer U> ? Array<MapDeep<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<MapDeep<U>> : T extends Set<infer U> ? Set<MapDeep<U>> : T extends Map<infer K, infer V> ? Map<K, MapDeep<V>> // 新增:提前匹配所有函数类型,直接返回原类型 : T extends Function ? T : T extends Partial<Record<string, any>> ? { [K in keyof T]: MapDeep<T[K]> } : T >;
调整后MapDeep<() => void>就会命中函数分支,返回你预期的F<() => void>,不会走到普通对象处理分支。
自定义类实例的处理
如果你的业务场景需要排除自定义类实例,受限于TS静态类型的限制,没有完美的通用方案,可选的折中方案有两个:
- 要求所有自定义类都加唯一的标识属性(比如
__isCustomClass = true),提前匹配带该属性的类型直接返回 - 可接受类实例公开属性被递归映射的话,不需要额外处理,现有逻辑可以正常运行
内容的提问来源于stack exchange,提问作者Leo Jiang
相关产品推荐
相关产品推荐

