如何让TypeScript拒绝包含特定字段的对象?
如何在TypeScript中强制函数参数不包含指定字段?
我需要实现一个TypeScript类型,确保传入函数的对象完全不包含指定的字段(比如UserDao中的email、_id等),只有额外字段的对象才合法。
现有代码如下:
type UserDao = { _id: string; email: string; authCode: number; authCodeExpirationDate: Date; createdAt: Date; updatedAt: Date; }; export type OnlyAdditionalFieldsUser<TUser> = Omit<TUser, keyof UserDao>; function getUserObject<TUser>( user: OnlyAdditionalFieldsUser<TUser> ) { return user; } type TestUser = { email: string; firstname: string; lastname: string; }; const user: TestUser = { email: 'test@test.com', firstname: 'John', lastname: 'Doe' }; console.log(getUserObject<TestUser>(user)); // 期望TypeScript报错,但实际没有
问题所在
当前的Omit<TUser, keyof UserDao>只是移除了指定字段的类型声明,但并没有禁止对象实际携带这些字段——TypeScript会忽略这些“额外”的字段,不会触发错误。
需要明确:我的需求和“禁止额外属性”的场景不同,我是要主动拒绝存在指定字段的对象,而非限制对象只能有预定义属性。另外,变量层面用satisfies可以实现校验,但我需要在函数参数层面完成这个限制。
解决方案
核心思路是:在Omit的基础上,给所有禁止字段添加never类型的约束——因为never类型没有合法取值,相当于强制这些字段不能存在。
修改后的代码:
type UserDao = { _id: string; email: string; authCode: number; authCodeExpirationDate: Date; createdAt: Date; updatedAt: Date; }; // 定义禁止的字段集合 type ForbiddenFields = keyof UserDao; // 核心类型:移除禁止字段的类型,同时强制这些字段不能存在 export type OnlyAdditionalFieldsUser<TUser> = Omit<TUser, ForbiddenFields> & { [K in ForbiddenFields]?: never; }; function getUserObject<TUser>( user: OnlyAdditionalFieldsUser<TUser> ) { return user; } type TestUser = { email: string; firstname: string; lastname: string; }; const user: TestUser = { email: 'test@test.com', firstname: 'John', lastname: 'Doe' }; console.log(getUserObject<TestUser>(user)); // 现在TypeScript会报错:属性"email"的类型不兼容
优化泛型推断
如果不想手动指定泛型参数,可以调整函数的泛型约束,让TypeScript自动推断并校验:
function getUserObject<T extends OnlyAdditionalFieldsUser<T>>( user: T ) { return user; } // 直接调用即可触发报错 console.log(getUserObject(user));
原理说明
Omit<TUser, ForbiddenFields>负责保留允许的字段类型,而& { [K in ForbiddenFields]?: never; }则添加了一个冲突约束:所有禁止字段要么不存在,要么类型必须是never(没有合法值)。当传入的对象包含禁止字段时,TypeScript会检测到类型冲突,从而抛出错误。
内容的提问来源于stack exchange,提问作者TheSmartMonkey
相关产品推荐
相关产品推荐

