如何无需新建类型从TypeScript已有类型生成指定键白名单类型?
TypeScript 基于已有类型实现白名单属性约束(无需新建类型)
问题描述
我有如下TypeScript类型:
interface Koko { a?: string, b?: number, c?: string[], d?: number[] }
希望基于该类型实现仅允许使用a、b键的白名单约束:传入c或d时触发类型检查错误,传入符合类型的a或b时通过检查,最终效果等价于手动定义如下类型:
interface PartialKoko { a?: string, b?: number, }
请问是否可以无需新建类型实现该需求?
实现方案
可以实现,核心是利用TypeScript的类型组合特性,通过Pick、Exclude和Record类型的组合,在变量声明或函数参数中直接施加约束,无需单独定义新类型。
方案1:变量声明时直接约束
在声明变量时,通过类型交集同时提取允许的属性、禁止多余属性:
const validObj: Pick<Koko, 'a' | 'b'> & Record<Exclude<keyof Koko, 'a' | 'b'>, never> = { a: 'hello', b: 789 }; // 以下写法会触发类型错误 // const invalidObj: Pick<Koko, 'a' | 'b'> & Record<Exclude<keyof Koko, 'a' | 'b'>, never> = { // c: ['test'] // };
Pick<Koko, 'a' | 'b'>:提取Koko中a、b两个属性的可选类型Record<Exclude<keyof Koko, 'a' | 'b'>, never>:将Koko中除a、b外的c、d键约束为never类型,一旦赋值就会触发类型检查错误
方案2:泛型函数约束(适合参数校验)
如果需要在函数参数中应用该约束,可以写一个泛型函数,直接在参数类型中组合约束逻辑:
function onlyAllowAB<T extends Pick<Koko, 'a' | 'b'> & Record<Exclude<keyof Koko, 'a' | 'b'>, never>>(obj: T) { return obj; } // 合法调用,无错误 onlyAllowAB({ a: 'valid' }); onlyAllowAB({ b: 100 }); // 非法调用,触发类型错误 // onlyAllowAB({ c: ['invalid'] }); // onlyAllowAB({ a: 'ok', d: [1, 2] });
这种方式不需要提前定义PartialKoko类型,直接通过泛型和类型组合实现了白名单属性的校验逻辑。
内容的提问来源于stack exchange,提问作者noer
相关产品推荐
相关产品推荐

