TypeScript映射类型:如何根据值条件移除指定键?
优化映射类型实现 + 解答
never属性的困惑 首先,先解决你关于{ key: never }的困惑:TypeScript中,即使属性的类型是never,这个属性依然会保留在类型结构中——它只是意味着没有任何值可以赋值给这个属性(因为never没有子类型),但类型本身仍然包含这个键。如果想要省略某个键,需要通过条件类型主动不包含它,或者用Omit工具类型移除它。
接下来,针对你的需求,我们可以优化掉交叉类型,用更直观的条件分支直接生成目标类型:
type DataParams = { trade: never; trade_bar: { interval: number; intervalUnit: "ms" | "s" | "m" | "ticks" | "vol"; }; }; type DataTypes = keyof DataParams; // 直接通过条件分支返回带/不带params的结构 type OptionsForDataType<T extends DataTypes> = DataParams[T] extends never ? { type: T } : { type: T; params: DataParams[T] }; // 利用条件类型的自动分发特性,直接生成联合类型 type Options = OptionsForDataType<DataTypes>;
这个写法的优势在于:
- 完全避免了交叉类型,逻辑更直白:当
DataParams[T]是never时,只返回{ type: T };否则返回包含params的完整结构。 - 利用TypeScript条件类型的联合分发特性:当
T是联合类型(DataTypes)时,OptionsForDataType<DataTypes>会自动遍历联合中的每个成员,生成对应的子类型,最终合并成你需要的联合类型,效果和你之前的映射类型索引访问完全一致。
如果你偏好映射类型的写法,也可以用as子句来过滤属性,但上面的条件分支写法已经足够简洁了。
另外,再补充一点:如果你的场景更复杂,需要在已有类型上动态移除never类型的属性,可以用下面的工具类型:
type OmitNeverProperties<T> = { [K in keyof T as T[K] extends never ? never : K]: T[K]; };
这个类型会遍历T的所有键,把类型为never的键过滤掉,比如OmitNeverProperties<{ type: 'trade'; params: never }>会得到{ type: 'trade' }。不过在你的场景中,前面的条件分支写法已经更直接了。
内容的提问来源于stack exchange,提问作者hackape
相关产品推荐
相关产品推荐

