Creating combinations of unions that only hold property keys can be achieved like this:
type KeyCombos<T extends PropertyKey> = {
[K in T]: [K] | (KeyCombos<Exclude<T, K>> extends infer U extends any[] ? U extends U ? [K | U[number]] : never : never);
}[T];
The reason for this limitation is that mapped types only allow property keys. Here are some examples of using this type (wrapped in tuples to prevent simplification into the original union):
type S = KeyCombos<"a" | "b" | "c">;
// ^? ["a"] | ["b"] | ["c"] | ["b" | "c"] | ["a" | "b"] | ["a" | "c"] | ["a" | "b" | "c"]
type N = KeyCombos<1 | 2 | 3>;
// ^? [1] | [2] | [3] | [2 | 3] | [1 | 2] | [1 | 3] | [1 | 2 | 3]
To make this work for any kind of union, I tried using distributive conditionals but it didn't work out as expected. Attempt 1 failed due to the simplification of Exclude<T, T>
to never
. Attempt 2 yielded the same results.
If you have a solution for making this work for any union without permutations with tuples, please share! This challenge is all about having fun with typings and exploring possibilities.
P.S. If there's a similar question that I missed, feel free to point it out for reference.
P.S.S. Just to clarify, this isn't meant for a specific project, just an enjoyable coding exercise!