打字稿:映射类型,联合中的剥离字段
Typescript: mapped types, strip field from a union
我正在尝试创建一个类型映射器 NewRecord<T>
,它将从 <T>
中去除 id
类型。
我就是这样做的:
type NewRecord<T> = {
[P in Exclude<keyof T, 'id'>]: T[P]
}
但是,不幸的是,它不适用于联合类型。让我举例说明:
interface IRecord {
id: number
}
interface IBotRecord extends IRecord {
isBot: true
cpuCores: 4
}
interface IHumanRecord extends IRecord {
isBot: false
isHungry: true
}
type ICreature = IHumanRecord | IBotRecord
type INewBotRecord = NewRecord<IBotRecord>
type INewHumanRecord = NewRecord<IHumanRecord>
type INewCreature = NewRecord<ICreature>
const newHuman:INewHumanRecord = {
isBot: false,
isHungry: true // works!
}
const newCreature:INewCreature = {
isBot: false,
isHungry: true // does not exist in type NewRecord<ICreature>
}
这是因为 keyof
遍历类型的交集,而不是联合,这是预期的行为:https://github.com/Microsoft/TypeScript/issues/12948
从联合中剥离字段的正确方法是什么?
您想为联盟的每个成员应用映射类型。幸运的是,条件类型具有这种确切的行为,它们分布在裸类型参数上。这意味着映射类型独立应用于联合的每个成员,并且所有结果都联合到最终类型中。有关更多说明,请参阅 here and 。
在这种情况下,条件类型中的条件可以只是extends any
我们不关心条件部分我们只关心条件类型的分布行为:
type NewRecord<T> = T extends any ? {
[P in Exclude<keyof T, 'id'>]: T[P]
} : never
type INewCreature = NewRecord<ICreature>
// The above type is equivalent to
type INewCreature = {
isBot: false;
isHungry: true;
} | {
isBot: true;
cpuCores: 4;
}
const newCreature:INewCreature = {
isBot: false,
isHungry: true // works fine
}
我正在尝试创建一个类型映射器 NewRecord<T>
,它将从 <T>
中去除 id
类型。
我就是这样做的:
type NewRecord<T> = {
[P in Exclude<keyof T, 'id'>]: T[P]
}
但是,不幸的是,它不适用于联合类型。让我举例说明:
interface IRecord {
id: number
}
interface IBotRecord extends IRecord {
isBot: true
cpuCores: 4
}
interface IHumanRecord extends IRecord {
isBot: false
isHungry: true
}
type ICreature = IHumanRecord | IBotRecord
type INewBotRecord = NewRecord<IBotRecord>
type INewHumanRecord = NewRecord<IHumanRecord>
type INewCreature = NewRecord<ICreature>
const newHuman:INewHumanRecord = {
isBot: false,
isHungry: true // works!
}
const newCreature:INewCreature = {
isBot: false,
isHungry: true // does not exist in type NewRecord<ICreature>
}
这是因为 keyof
遍历类型的交集,而不是联合,这是预期的行为:https://github.com/Microsoft/TypeScript/issues/12948
从联合中剥离字段的正确方法是什么?
您想为联盟的每个成员应用映射类型。幸运的是,条件类型具有这种确切的行为,它们分布在裸类型参数上。这意味着映射类型独立应用于联合的每个成员,并且所有结果都联合到最终类型中。有关更多说明,请参阅 here and
在这种情况下,条件类型中的条件可以只是extends any
我们不关心条件部分我们只关心条件类型的分布行为:
type NewRecord<T> = T extends any ? {
[P in Exclude<keyof T, 'id'>]: T[P]
} : never
type INewCreature = NewRecord<ICreature>
// The above type is equivalent to
type INewCreature = {
isBot: false;
isHungry: true;
} | {
isBot: true;
cpuCores: 4;
}
const newCreature:INewCreature = {
isBot: false,
isHungry: true // works fine
}