#typescript #casting #type-conversion #prisma #prisma2
#typescript #Кастинг #преобразование типов #prisma #prisma2
Вопрос:
Я работаю с Prisma для создания схем и моделей для данных моей базы данных.
Там я определяю «пользовательскую» модель, в которой есть эти данные (тип автоматически генерируется Prisma):
type User {
name: string,
nickName: string,
sensitiveInfo1: string,
sensitiveInfo2: string
}
Однако, когда мой клиент запрашивает эти данные, я не могу отправить конфиденциальную информацию в полезной нагрузке ответа.
У Prisma есть очень удобный способ определения пользовательского типа:
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>
// }
Теперь предположим, что у меня уже есть экземпляр пользователя, извлеченный из базы данных, типа User . Я не хочу приводить его к «UserPublicInfo» таким образом, чтобы полезная нагрузка ответа содержала только информацию «UserPublicInfo».
Если я приведу объект типа User, подобный user as UserPublicInfo
предложениям типа, указывает правильное направление, показывая только атрибуты подтипа. Однако конфиденциальные данные все еще там.
Я младший в javascipt / typescript, но я считаю, что это как-то связано с прототипом объекта. Итак, как я могу использовать его таким образом?
Ответ №1:
В этом вопросе есть две части: как сообщить typescript, что свойства исчезли, и как их фактически удалить.
Typescript
То, что вы ищете, это утилиты typescript, которые выбирают и опускают.
Чтобы получить только поля name
и nickName
из User
:
type UserPublicInfo = Pick<User, 'name' | 'nickName'>
Чтобы получить все поля, User
кроме sensitiveInfo1
и sensitiveInfo2
:
type UserWithoutPrivate = Omit<User, 'sensitiveInfo1' | 'sensitiveInfo2'>
В приведенном вами примере оба этих типа идентичны и разрешаются в
type UserPublicInfo = {
name: string;
nickName: string;
}
Javascript
Теперь для удаления свойств. Проще всего использовать функции pick
и omit
из пакета Lodash . Они имеют встроенную поддержку typescript, поэтому вам не нужно знать ни о чем из того, что я вам только что рассказал.
Если вы хотите сделать это самостоятельно, вы можете использовать оператор распространения, чтобы удалить ненужные свойства (примечание: некоторые линтеры будут жаловаться на неиспользуемые переменные здесь).
export const userToPublic = (user: User): UserPublicInfo => {
const {sensitiveInfo1, sensitiveInfo2, ...rest} = user;
return user;
}
Комментарии:
1. Ваш ответ идеален! Спасибо. Могу ли я каким-либо образом указать Lodash или самому typescript выбрать все элементы, определенные подтипом? Например, _.pick(User, UserPublicInfo) . Это было бы намного лучше, чем явно выбирать атрибуты, определенные подтипом.
2. Кстати, последняя строка вашего примера в ссылке TS playground была немного сломана, вы тоже заметили?