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

Я работаю с 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, но считаю, что это как-то связано с прототипом объекта. Итак, как я могу использовать это таким образом?


person Teodoro    schedule 19.10.2020    source источник


Ответы (1)


В этом вопросе есть две части: как сообщить машинописному тексту, что свойства исчезли, и как их удалить.

Машинопись

Вам нужны утилиты машинописного текста Pick и Пропустить.

Чтобы получить только поля 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. В них есть встроенная поддержка машинописного текста, поэтому вам не нужно ничего знать о TS, о котором я вам только что рассказал.

Если вы хотите сделать это самостоятельно, вы можете использовать оператор распространения, чтобы удалить свойства, которые вам не нужны (примечание: здесь некоторые линтеры будут жаловаться на неиспользуемые переменные).

export const userToPublic = (user: User): UserPublicInfo => {
    const {sensitiveInfo1, sensitiveInfo2, ...rest} = user;
    return user;
}

Машинопись площадка Link

person Linda Paiste    schedule 19.10.2020
comment
Ваш ответ идеален! Спасибо. Могу ли я как-то сказать lodash или машинописному тексту выбрать все элементы, определенные подтипом? Как _.pick (Пользователь, UserPublicInfo). Это было бы намного лучше, чем явный выбор атрибутов, определенных подтипом. - person Teodoro; 20.10.2020
comment
Кстати, последняя строка вашего примера в ссылке на игровую площадку TS была как бы сломана, вы тоже заметили? - person Teodoro; 20.10.2020