Given this input:
export type Test = {
one: {
a: string;
b: string;
c: string;
};
two: {
a: string;
b: string;
d: string;
};
}
I need a generics like CombinedChildren<T>
which outputs the following type:
export type Combined = {
a?: string;
b?: string;
c?: string;
d?: string;
}
Basically, it takes the children properties and combines them, including them even if they're not present in all children.
Tried
export type KeyOfTest = Partial<Test[keyof Test]>
export type MappedKeyOfTest = Partial<{
[key in keyof Test[keyof Test]]: Test[keyof Test][key]
}>
But none output exactly what want.
CodePudding user response:
We can break this down into a few steps. First, we get a union of all the child types by Test[keyof Test]
. Then we want a union of all this type, so we use a utility type that converts union types to intersection types (taken from this answer by @jcalz). Finally, we apply Partial
to the resulting type.
export type Test = {
one: {
a: string;
b: string;
c: string;
};
two: {
a: string;
b: string;
d: string;
};
three: {
a: string;
e: number;
}
}
// union to intersection converter by @jcalz: https://stackoverflow.com/a/50375286/8580499
// Intersect<{ a: 1 } | { b: 2 }> = { a: 1 } & { b: 2 }
type Intersect<T> = (T extends any ? ((x: T) => 0) : never) extends ((x: infer R) => 0) ? R : never;
// Combined = { a?: string; b?: string; c?: string; d?: string; e?: number }
type Combined = Partial<Intersect<Test[keyof Test]>>;
CodePudding user response:
How about using union operator:
export type Combined = Test['one'] & Test['two'];
OR
export type Combined = Partial<Test['one'] & Test['two']>;