Преобразовать объект в объект , где A содержится в T

#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;
}
  

Ссылка на игровую площадку Typescript

Комментарии:

1. Ваш ответ идеален! Спасибо. Могу ли я каким-либо образом указать Lodash или самому typescript выбрать все элементы, определенные подтипом? Например, _.pick(User, UserPublicInfo) . Это было бы намного лучше, чем явно выбирать атрибуты, определенные подтипом.

2. Кстати, последняя строка вашего примера в ссылке TS playground была немного сломана, вы тоже заметили?