admin管理员组

文章数量:1390642

I want to create a TypeScript type that removes specific fields from an object type and ensures that objects passed to a function do not contain any of these fields.

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: '[email protected]', firstname: 'John', lastname: 'Doe' };

console.log(getUserObject<TestUser>(user)); // TypeScript should give an error because email is in user

If user contains any field from UserDao (email, ...), TypeScript should give an error. If user only contains additional fields (e.g., firstname, lastname), it should be valid.

However, the function getUserObject(user) does not trigger a TypeScript error even though user contains email, which is in UserDao. It seems like TypeScript allows extra fields rather than enforcing strict exclusions.

How can I make TypeScript enforce that user does not contain any fields from UserDao?

My question is not the same as Avoid extra properties

My question is about forbidding specific fields (email, _id, ...) from being present in an object. I want TypeScript to reject objects that include any of these fields

The other question is about preventing extra properties that are not part of a predefined type. It focuses on ensuring an object has only the allowed properties, rather than excluding specific ones

At the variable level satisfy does the good stuff but I am trying to do it at the function level:

const user = { email: '[email protected]', firstname: 'John', lastname: 'Doe' } satisfies OnlyAdditionalFieldsUser<TestUser>; // The Error is thrown on email

I want to create a TypeScript type that removes specific fields from an object type and ensures that objects passed to a function do not contain any of these fields.

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: '[email protected]', firstname: 'John', lastname: 'Doe' };

console.log(getUserObject<TestUser>(user)); // TypeScript should give an error because email is in user

If user contains any field from UserDao (email, ...), TypeScript should give an error. If user only contains additional fields (e.g., firstname, lastname), it should be valid.

However, the function getUserObject(user) does not trigger a TypeScript error even though user contains email, which is in UserDao. It seems like TypeScript allows extra fields rather than enforcing strict exclusions.

How can I make TypeScript enforce that user does not contain any fields from UserDao?

My question is not the same as Avoid extra properties

My question is about forbidding specific fields (email, _id, ...) from being present in an object. I want TypeScript to reject objects that include any of these fields

The other question is about preventing extra properties that are not part of a predefined type. It focuses on ensuring an object has only the allowed properties, rather than excluding specific ones

At the variable level satisfy does the good stuff but I am trying to do it at the function level:

const user = { email: '[email protected]', firstname: 'John', lastname: 'Doe' } satisfies OnlyAdditionalFieldsUser<TestUser>; // The Error is thrown on email
Share Improve this question edited Mar 16 at 18:00 jonrsharpe 122k30 gold badges268 silver badges476 bronze badges asked Mar 16 at 17:17 TheSmartMonkeyTheSmartMonkey 1,0921 gold badge13 silver badges29 bronze badges 5
  • 1 "It seems like TypeScript allows extra fields..." - yes; it's structurally typed, and excess property checks only occur in certain circumstances. – jonrsharpe Commented Mar 16 at 17:21
  • 1 This question is similar to: Avoid extra properties. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. – jonrsharpe Commented Mar 16 at 17:22
  • As you requested I've edited my question. I've tried some stuff but it's not the same as the other question I want different not exact – TheSmartMonkey Commented Mar 16 at 17:46
  • 1 i've extended my answer to match your demands more closely – Alexander Nenashev Commented Mar 16 at 18:44
  • 1 Thanks for the solution ! To answer your question : "Also note that you don't specify which extra fields could exist which seems strange" It's because I'm writing a library where the goal is to allow flexibility for additional fields while still omitting specific ones like email, which is why I haven't explicitly defined extra fields – TheSmartMonkey Commented Mar 16 at 18:46
Add a comment  | 

1 Answer 1

Reset to default 1

You could make sure that keys of the argument don't intersect with UserDao.

Playground

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 extends OnlyAdditionalFieldsUser<TestUser>>(
  user: keyof TUser & keyof UserDao extends never ? TUser: never
) {
  return user;
}

type TestUser = {email: string, firstname: string, lastname: string};

const user = { email: '[email protected]', firstname: 'John', lastname: 'Doe'} satisfies OnlyAdditionalFieldsUser<TestUser>
const user2 = { firstname: 'John', lastname: 'Doe' } satisfies OnlyAdditionalFieldsUser<TestUser>


getUserObject(user); // TypeScript should give an error because email is in user
getUserObject(user2); // OK

本文标签: How to make TypeScript reject objects containing certain fieldsStack Overflow