I'm trying to delete the password
key in a user object in a typesafe way but typescript keeps complaining.
const user = db.findUnique({where: email:input.email});
// returning user without password
// OPTION 1 - eslint disable doesn't remove the yellow squiggly on the password variable
// @eslint-disable-next-line @typescript-eslint/no-unused-vars
const { password, ...userWithoutPassword } = user;
return userWithoutPassword;
// OPTION 2 - Unsafe return of an `any` typed value.eslint@typescript-eslint/no-unsafe-assignment
return omit(user, "password"); // using lodash
// this also leads to the same error
const userWithoutPassword: Omit<User, "password"> = omit(user, "password");
return userWithoutPassword;
// OPTION 3 - The operand of a 'delete' operator must be optional.
// I don't want to change the type definition of User to make password optional. It should be a new type
delete user.password;
return user;
What's the appropriate way to do this?
The return type for lodash
's omit
(source) should produce a type that is structurally compatible with the desired type Omit<User, "password">
. It sounds like there might be a configuration issue in your project if you are seeing any
as the return type of the omit
function. (Have you installed @types/lodash
in your project?) See example in this playground.
If, for some reason, you want to mutate the existing user
object by deleting the password
property (instead of creating a new object), you will have to use some type assertions in order to satisfy the compiler because it does not allow for modifying types in-place — see functional predicates (a.k.a. type guards) for more.
Here's an example:
type User = {
name: string;
id: string;
email: string;
password: string;
// etc.
};
function getUserWithoutPassword (): Omit<User, "password"> {
// const user = db.findUnique({where: email:input.email});
const user: User = {
name: "Foo",
id: "abc123",
email: "foo@bar.baz",
password: "1_bad_password",
};
delete (user as Partial<Pick<User, "password">>).password;
return user as Omit<User, "password">;
}
delete (user as Partial<Pick<User, "password">>).password;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the statement above, user
is being asserted as the type { password?: string }
, so the compiler will allow deletion of the optional value.
return user as Omit<User, "password">;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
And in the return
statement, user
is being asserted as a type that represents the result of the previous deletion operation.