如何创建含动态字符串键与特定固定键的TypeScript对象类型?
如何定义兼容通用字符串键与特定特殊键的TypeScript类型?
背景
我正在开发一个可动态生成GraphQL查询过滤器的应用,需要创建一个符合过滤器允许结构的TypeScript类型。
需求
所需的TypeScript类型需满足:
- 所有普通字符串键对应值为类型A(示例中为
string) - 仅特定键(如
"AND"和"OR")对应值为不同类型B(示例中为过滤器数组)
符合要求的过滤器示例
let filter = { "fieldA": "2015-10-08", "fieldB": "This is the search input string...", OR: [ {"fieldC1": "deleted"}, { AND: [ {"fieldD": "null"}, {"fieldE": "inactive"} ]} ], }
尝试过的无效方案
方案一:索引签名与显式属性直接交集
type CustomTypeBase = { [key: string]: string; } & { AND?: Array<{[key: string]: string} | CustomTypeBase>; OR?: Array<{[key: string]: string} | CustomTypeBase>; };
问题:TypeScript会强制所有字符串键(包括"AND"和"OR")的值都必须是string类型,与显式属性的类型冲突,导致类型无效。
方案二:使用Omit工具类型
type CustomTypeWithOmit = Omit<{ [key: string]: string; }, 'AND' | 'OR'> & { AND?: Array<{[key: string]: string} | CustomTypeWithOmit>; OR?: Array<{[key: string]: string} | CustomTypeWithOmit>; };
问题:Omit仅能处理对象的具名属性,无法作用于string这种通用索引签名,因此无法剔除AND/OR键的索引约束,类型仍无效。
核心问题
是否存在一种TypeScript类型定义方式,能让所有普通字符串键对应类型A,仅特定键对应类型B?
解决方案
可以通过映射类型+显式属性交集的方式实现需求,具体类型定义如下:
type Filter = { [K in string]: K extends 'AND' | 'OR' ? never : string; } & { AND?: Filter[]; OR?: Filter[]; };
原理说明
- 映射类型
{ [K in string]: K extends 'AND' | 'OR' ? never : string }定义了:- 所有字符串键中,若键名是
AND或OR,则值类型为never(表示这类键不允许通过索引签名赋值) - 其余普通字符串键的值类型必须为
string
- 所有字符串键中,若键名是
- 与包含
AND/OR显式属性的对象类型取交集后,TypeScript会优先使用显式属性的类型定义,因此AND/OR键的值类型会被覆盖为Filter[] | undefined,完美满足需求。
验证示例
使用上述类型后,示例中的过滤器对象可以通过类型检查:
let filter: Filter = { "fieldA": "2015-10-08", "fieldB": "This is the search input string...", OR: [ {"fieldC1": "deleted"}, { AND: [ {"fieldD": "null"}, {"fieldE": "inactive"} ]} ], }; // 类型检查通过
通用泛型版本
如果需要支持自定义字段值类型和操作符值类型,可以封装为泛型:
type GenericFilter<FieldValue = string, OperatorValue = GenericFilter<FieldValue>[]> = { [K in string]: K extends 'AND' | 'OR' ? never : FieldValue; } & { AND?: OperatorValue; OR?: OperatorValue; }; // 使用示例:定义字段值为数字的过滤器 type NumberFilter = GenericFilter<number>;
内容的提问来源于stack exchange,提问作者mitras2
相关产品推荐
相关产品推荐

