📄

【TS技巧】通过 in 操作符将联合类型转换为另一个联合类型

2023-04-30 1 min read

首先,我们给出下面👇🏻这段代码,我们期望将当前实体单独转换为 `user` `post` `comment`

export type Entity =

| {

type: "user"

}

| {

type: "post"

}

| {

type: "comment"

}

const user:EntityWithId = {

type: "user"

userId: string

}

const post:EntityWithId = {

type: "post"

postId: string

}

const comment:EntityWithId = {

type: "comment"

commentId: string

}

我们手动的给每个类型增加对应的 `id` 属性就是实现了我们所期望的 `EntityWithId`

type EntityWithId =

| {

type: "user"

userId: string

}

| {

type: "post"

postId: string

}

| {

type: "comment"

commentId: string

}

但是这看起来有些繁琐,我们该如何优化它呢?首先,我们先使用`[Key in Type]` 语法来遍历我们每个实体的`type`,并添加一个`type`属性, 属性值为我们每次遍历实体的 `type`值类型

type EntityWithId = {

[EntityType in Entity['type']]:{

type:EntityType

}

}

然后,我们将这个对象类型转换为联合类型

type EntityWithId = {

[EntityType in Entity['type']]:{

type:EntityType

}

}[Entity["type"]]

这意味着我们可以单独得到 `user` 类型 `comment`类型 或者`post`类型

const result = (EntityWithId = {

type: "comment",

})

当然这还没结束,我们还需要添加相应的`id`属性,这时候就需要使用 `Record` 方法,将id属性变为动态的

type EntityWithId = {

[EntityType in Entity["type"]]: {

type: EntityType

} & Record<`${EntityType}Id`, string>//与EntityType拼接实现动态ID

}[Entity["type"]]

这样就可以实现我们想要的结果🎉

const commentResult: EntityWithId = {

type: "comment",

commentId: "123",

}

const userResult: EntityWithId = {

type: "user",

userId: "123",

}

const postResult: EntityWithId = {

type: "post",

postId: "123",

}

End of file