如何创建仅接受可选或数组类型的TypeScript映射类型?
解决方案:约束对象属性为可选原始类型或原始类型数组
首先明确核心需求:对象的属性只能是可选原始类型(Primitive | undefined)或原始类型数组(Primitive[]),严格禁止必填的原始类型。你之前的写法失效是因为(Primitive | undefined) | Primitive[]包含了纯Primitive类型,无法排除必填原始属性的情况。
实现代码
type Primitive = number | string | boolean | object | symbol; // 定义允许的属性类型范围 type AllowedProp = Primitive[] | (Primitive | undefined); // 双重约束:确保属性属于允许范围,且禁止必填原始类型 type ValidSelectorProps<T> = // 第一步:限定所有属性必须是允许的类型 { [K in keyof T]: AllowedProp } & // 第二步:检查属性是否为必填原始类型,是则返回never触发错误 { [K in keyof T]: T[K] extends Primitive ? undefined extends T[K] ? unknown : never : unknown }; // 用于验证类型的示例函数 function processSelector<T>(props: ValidSelectorProps<T>): T { return props as T; }
验证效果
兼容合法类型(对应你的T1)
// 显式包含undefined的属性,合法 const validProps1 = { a: true as boolean | undefined, b: {} as Object | undefined, c: ['foo', 'bar'] as string[] }; processSelector(validProps1); // 可选属性(自动隐含undefined),合法 const validProps2 = { a?: boolean, b?: Object, c: ['foo'] as string[] }; processSelector(validProps2);
拦截非法类型(对应你的T2)
// 报错:属性a是必填的boolean(纯原始类型),不符合约束 const invalidProps = { a: true, b: ['test'] as string[] | undefined }; processSelector(invalidProps);
原理说明
AllowedProp先圈定属性的可选范围:要么是原始类型数组,要么是带undefined的原始类型。- 第二个交叉类型通过条件判断,对每个属性做二次校验:如果属性类型是纯
Primitive且不包含undefined,则返回never,直接触发TypeScript类型错误,从而禁止必填原始类型的属性。
内容的提问来源于stack exchange,提问作者Milos Pavlovic
相关产品推荐
相关产品推荐

