To create a utility type that takes in a type with multiple properties and produces an union of types where each individual member corresponds to one of the keys of the original multi-property type, you could do something like this:
type Split<T> = { [K in keyof T]: Pick<T, K> }[keyof T]
This will mean the following:
type Foo = {
a: A,
b: B,
c: C
}
type Bar = Split<Foo>
// ~~~
// Bar = Pick<Foo, "a"> | Pick<Foo, "b"> | Pick<Foo, "c">
// = { a: A } | { b: B } | { c: C }
Now, I understand you want IntelliSense to not suggest the other properties, like it does here:
type Foo = { a: number, b: string }
const foo: Split<Foo> = { a: 0, … }
// ^
// | + (property) b: string
But I'm not aware of a way to make TypeScript totally ignore the existence of b: String
, since { a: number, b: string } extends { a: number } | { b: string }
; as long as the shape of a value satisfies the type assigned to it, TypeScript will allow it. The TypeScript language service in your editor is "smart enough" to know to suggest the possible properties to you — it's not directly related to the type system itself and you cannot influence it in this case.
Since you wanted to have the other properties set to never
in the union, you could do something like:
type Split<T> = {
[K in keyof T]:
Pick<T, K> &
Partial<
Record<
Exclude<keyof T, K>,
never
>
>;
}[keyof T]
Now you'll have:
type Foo = {
a: A,
b: B,
c: C
}
type Bar = Split<Foo>
// ~~~
// Bar = (Pick<Foo, "a"> & Partial<Record<"b" | "c", never>>)
// | (Pick<Foo, "b"> & Partial<Record<"a" | "c", never>>)
// | (Pick<Foo, "c"> & Partial<Record<"a" | "b", never>>)
// = ({ a: A } & { b?: never, c?: never })
// | ({ b: B } & { a?: never, c?: never })
// | ({ c: C } & { a?: never, b?: never })
// = ({ a: A, b?: never, c?: never })
// | ({ b: B, a?: never, c?: never })
// | ({ c: C, a?: never, b?: never })
At least with the current TSC version, the errors this approach produces seem to be misleading and generally hard to read anyhow. I found another post with this problem addressed by Jcalz; they have a more elegant solution: https://stackoverflow.com/a/57576688/11308378