TypeScript 自定义递归剔除空值类型无法访问嵌套键问题
问题原因
- 你实现的
OmitNullishKeys工具类型没有预先排除输入泛型T本身携带的null | undefined值,就直接取keyof T进行遍历:当T是包含null/undefined的联合类型时,keyof T会返回never(因为null/undefined没有任何属性,联合类型取属性键的逻辑是取所有成员共有的属性键,没有共有键就返回never),此时TypeScript无法对映射类型做进一步展开计算,会保留原始的OmitNullishKeys<xxx>包装类型,自然无法识别到内部的forums属性。 - 当前实现也没有兼容可选属性的处理逻辑,可选属性的类型默认隐式包含
undefined,也需要提前剔除。
修复方案
在处理泛型T的第一步先排除nullish值,再做后续递归处理,修正后的工具类型代码如下:
export type OmitNullish<T> = Exclude<T, null | undefined>; export type OmitNullishKeys<T> = // 先剔除T本身的null/undefined,得到非空类型U OmitNullish<T> extends infer U ? U extends Record<string | number | symbol, any> ? { // 遍历U的所有属性键,移除可选标记 [K in keyof U]-?: U[K] extends boolean | string | number | symbol ? OmitNullish<U[K]> : OmitNullishKeys<U[K]> } // 如果U是基础类型,直接返回剔除nullish后的结果 : OmitNullish<U> : never;
效果验证
用你提供的测试代码验证,不会再抛出属性不存在的错误:
export type RandomObj = OmitNullishKeys<{ stackOverflow: { forums?: { thread1: 'not available'; } | null; } | null; }>; // 可以正常访问嵌套属性 export type RandomObjectAccessed = RandomObj['stackOverflow']['forums']; // 推导的类型结果为:{ thread1: 'not available' }
内容的提问来源于stack exchange,提问作者Urmzd
相关产品推荐
相关产品推荐

