这是Is there an alternative to type union which includes optional properties present only in some alternatives?的递归版本.那里的解决方案给出了
type AllKeys<T> = T extends unknown ? keyof T : never;
type Exactify<T, K extends PropertyKey = AllKeys<T>> =
T extends unknown ? T & Partial<Record<Exclude<K, keyof T>, never>> : never;
type Test = Exactify<X | Y>;
type Optionalize<T> = Omit<Exactify<T>, never>;
type X = { id: number, x: number };
type Y = { id: string, y: number };
type Z = Optionalize<X | Y>;
/* type Z = {
id: string | number;
x?: number | undefined;
y?: number | undefined;
} */
然而,现在让我们假设像本例中的id
这样的共享属性本身可以是对象类型.然后我们就会得到
type X1 = { shared: { x1: number }, x: number };
type Y1 = { shared: { y1: string }, y: number };
type Z1 = Optionalize<X1 | Y1>;
/* type Z1 = {
shared: { x1: number } | { y1: string };
x?: number | undefined;
y?: number | undefined;
} */
如果that有任何共享对象类型属性,我更喜欢shared: { x1?: number, y1?: number }
等等.
仍然可以安全地假设这些类型的对象没有任何额外的属性(包括一种类型的属性在另一种类型中缺失).
一种只适用于某一深度且易于调整的解决方案是可以接受的,但当然,如果它在任何深度都有效,那就更好了.