如何在打字稿中将对象类型转换为联合?
How to transform object type to union in typescript?
例如,我有一个 EventMapping 类型,它是一个映射“eventName -> eventData”。我需要将发出的事件存储在列表中。因此,我想将此映射转换为事件类型,因此我无法将不正确类型的数据推送到事件列表中。
// type which i have
type EventMapping = {
click: {
position: Point;
};
scroll: {
top: number;
bottom: number;
};
}
// type which i want to get
type Event = {
type: 'click';
data: {
position: Point;
};
} | {
type: 'scroll';
data: {
top: number;
bottom: number;
};
}
// usage example
const events: Event[] = [];
// ok
events.push({
type: 'scroll',
data: {
top: 0,
bottom: 0,
}
});
// error
events.push({
type: 'click',
data: {
top: 0,
bottom: 0,
}
});
我的策略是 2 个步骤:
将类型 EventMapping 转换为键的联合:所以目标是得到
“滚动” | “点击”
这可以通过 keyof 运算符
来完成
从这个联合中,我将其映射到您的事件类型。使用此处提到的技巧:
结果是:
type Distribute<U> = U extends keyof EventMapping? {type: U, data: EventMapping[U]} : never;
type Event = Distribute<keyof EventMapping>
使用 mapped type 的解决方案:
type ObjectToUnion<T> = {[K in keyof T]: {type: K, data: T[K]}}[keyof T]
type EventUnion = ObjectToUnion<EventMapping>
例如,我有一个 EventMapping 类型,它是一个映射“eventName -> eventData”。我需要将发出的事件存储在列表中。因此,我想将此映射转换为事件类型,因此我无法将不正确类型的数据推送到事件列表中。
// type which i have
type EventMapping = {
click: {
position: Point;
};
scroll: {
top: number;
bottom: number;
};
}
// type which i want to get
type Event = {
type: 'click';
data: {
position: Point;
};
} | {
type: 'scroll';
data: {
top: number;
bottom: number;
};
}
// usage example
const events: Event[] = [];
// ok
events.push({
type: 'scroll',
data: {
top: 0,
bottom: 0,
}
});
// error
events.push({
type: 'click',
data: {
top: 0,
bottom: 0,
}
});
我的策略是 2 个步骤:
将类型 EventMapping 转换为键的联合:所以目标是得到
“滚动” | “点击”
这可以通过 keyof 运算符
来完成从这个联合中,我将其映射到您的事件类型。使用此处提到的技巧:
结果是:
type Distribute<U> = U extends keyof EventMapping? {type: U, data: EventMapping[U]} : never;
type Event = Distribute<keyof EventMapping>
使用 mapped type 的解决方案:
type ObjectToUnion<T> = {[K in keyof T]: {type: K, data: T[K]}}[keyof T]
type EventUnion = ObjectToUnion<EventMapping>