使用Exclude时,映射类型的-?操作符为何无法移除可选性?
为什么结合Exclude后,映射类型的
-?操作符无法移除类型中的undefined? 先看我们的类型定义:
type Optinal = { a?: string; b?: number; }
直接用{ [K in keyof Optinal]-?: Optinal[K] }得到的Mapped1,确实能把可选字段变成必填,同时类型里的undefined也被去掉了。但换成Exclude排除字段后,Mapped2的a字段还是string | undefined,原因出在这两点:
1. 直接遍历keyof时的特殊处理
当你遍历keyof Optinal的时候,TypeScript会记住每个键的「可选性状态」。用-?操作符时,它不仅会去掉字段的?标记,还会自动把原可选字段类型里的undefined剔除——因为TS知道这个键原本是可选的,所以会同步清理类型里的undefined。所以Mapped1最终是{ a: string; b: number; }。
2. Exclude丢失了键的可选性元数据
Exclude<keyof Optinal, 'b'>返回的是"a"这个纯字符串字面量类型,它只是一个键名,没有携带原来的「可选」元数据。这时候Optinal[K]直接取的是原类型中a的完整类型(也就是string | undefined,因为原字段是可选的),而-?在这里只能处理字段的可选标记(但此时遍历的键已经是必填的了,所以-?等于没起作用),没法修改类型本身包含的undefined。所以Mapped2变成了{ a: string | undefined; }。
怎么解决?
如果想同时移除类型里的undefined,可以搭配NonNullable工具类型:
type Mapped2 = { [K in Exclude<keyof Optinal, 'b'>]-?: NonNullable<Optinal[K]> }; // 现在Mapped2的类型是 { a: string; }
内容的提问来源于stack exchange,提问作者jayatubi
相关产品推荐
相关产品推荐

