I'm working with Prisma to generate schemas and models for my database data.
There, I define a "User" model, which has this data (the type is automatically generated by Prisma):
type User {
name: string,
nickName: string,
sensitiveInfo1: string,
sensitiveInfo2: string
}
However, when my client requests this data, I can't send the sensitive info in the response payload.
Prisma has a very handy way for defining a custom type:
import { UserGetPayload } from "./prisma/src/generated/client"
// now I define a custom type
export type UserPublicInfo = UserGetPayload<{
select: {
name: true,
nickName: true,
}
}>
// this gives me the type:
// type UserPublicInfo {
// name: <whatever type name is in the schema>,
// nickName: <whatever type nickName is in the schema>
// }
Now, suppose I already have a user instance retrieved from the database, of type User. I wan't to cast it to "UserPublicInfo" in a way that the response payload only contains info of "UserPublicInfo".
If I cast an Object of type User like user as UserPublicInfo
the type suggestions points to the right direction, showing only attributes of the subtype. However, the sensitive data still there.
I'm junior at javascipt/typescript but I believe this has something to do with the Object's prototype. So how can I cast it this way?
There's two pieces to this question, how to tell typescript that the properties are gone and how to actually remove them.
Typescript
What you are looking for are the typescript utilities Pick and Omit.
To get only the fields name
and nickName
from User
:
type UserPublicInfo = Pick<User, 'name' | 'nickName'>
To get all fields from User
except for sensitiveInfo1
and sensitiveInfo2
:
type UserWithoutPrivate = Omit<User, 'sensitiveInfo1' | 'sensitiveInfo2'>
In the example you've given, both of these types are identical and resolve to
type UserPublicInfo = {
name: string;
nickName: string;
}
Javascript
Now for removing the properties. The easiest thing is to use the pick
and omit
functions from the package lodash. Those have built-in typescript support so you don't need to know about any of the TS stuff I just told you.
If you want to do it yourself, you can use the spread operator to drop the properties that you don't want (note: some linters will complain about unused variables here).
export const userToPublic = (user: User): UserPublicInfo => {
const {sensitiveInfo1, sensitiveInfo2, ...rest} = user;
return user;
}