TypeScript仅允许无!后缀键追加!的模板字面量类型约束方案
TypeScript 嵌套pick方法重复追加!后缀的类型约束问题
我之前尝试实现一个Schema类,既支持直接传入属性键作为参数,也支持传入属性键追加!后缀的形式,用来标记对应字段为必填项。
最终实现的类核心结构如下:
export class Schema<PropType extends Record<string, any>> { properties: Partial<PropType> = {}; constructor(properties: PropType) { this.properties = properties; } /** * 从已选中的字段范围内挑选指定字段 */ pick = <K extends keyof PropType | `${Extract<keyof PropType, string>}!`>( ...fields: Array<K> ) => { const newProperties = {} as Record<keyof PropType, unknown>; fields.forEach((field) => { const { name, required } = this._parse(field); newProperties[name] = { ...(this.properties[name]), required, }; }); return new Schema<Record<K, unknown>>( newProperties ); }; /** * 解析字段字符串,返回原始字段名,以及字段是否必填(以!结尾即为必填) */ _parse = (field: keyof PropType | `${Extract<keyof PropType, string>}!`) => { return { name: (field as string).replace("!", "") as keyof PropType, required: (field as string).split("").reverse()[0] === "!", }; }; }
pick方法是核心逻辑:只要keyName是PropType的合法键,就允许同时选取keyName和keyName!,其中!后缀代表该键为必填项。
基础使用没有问题:
const Person = new Schema({ firstName: 'Fyodor', middleName: 'Mikhailovich', lastName: 'Dostoevsky' }); const SubPerson = Person.pick('firstName', 'lastName!');
现存问题
嵌套多层pick调用时,类型系统会允许重复给字段追加感叹号后缀,以下非法传参不会触发类型报错:
SubPerson.pick( 'firstName', 'lastName!', 'lastName!!' // 该参数本不应被类型系统接受 )
需求
需要实现对应的类型约束:当且仅当keyof PropType对应的原始键本身不包含!后缀时,才允许使用${Extract<keyof PropType, string>}!形式的模板字面量类型,彻底阻断重复追加!的非法参数。
内容的提问来源于stack exchange,提问作者Sasha
相关产品推荐
相关产品推荐

