将 Object<T> 转换为 Object<A>,其中 A 包含在 T 中

Convert Object<T> to Object<A> where A is contained in 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 的大三学生,但我相信这与 Object 的原型有关。那我怎么才能这样投呢?

这个问题有两个部分,如何告诉打字稿属性已经消失以及如何实际删除它们。

打字稿

您正在寻找的是打字稿实用程序 Pick and Omit

仅从 User 获取字段 namenickName:

type UserPublicInfo = Pick<User, 'name' | 'nickName'>

User 中获取除 sensitiveInfo1sensitiveInfo2 之外的所有字段:

type UserWithoutPrivate = Omit<User, 'sensitiveInfo1' | 'sensitiveInfo2'>

在您给出的示例中,这两种类型是相同的并且解析为

type UserPublicInfo = {
    name: string;
    nickName: string;
}

Javascript

现在删除属性。最简单的方法是使用 lodash 包中的 pickomit 函数。它们具有 built-in 打字稿支持,因此您无需了解我刚刚告诉您的任何 TS 内容。

如果你想自己做,你可以使用扩展运算符来删除你不想要的属性(注意:一些 linters 会在这里抱怨未使用的变量)。

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

Typescript Playground Link