Skip to content

Instantly share code, notes, and snippets.

@hasparus
Created July 16, 2019 14:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasparus/cc61bff808843bc21d69c035fc0cf30c to your computer and use it in GitHub Desktop.
Save hasparus/cc61bff808843bc21d69c035fc0cf30c to your computer and use it in GitHub Desktop.
I'm sure it has no serious use case.
namespace Products {
export type Car = {
name: 'Car';
drive(): void;
}
export type IceCream = {
name: 'IceCream';
flavor: string;
}
export interface Registry {
Car: Car;
IceCream: IceCream;
}
}
const carScream = {
names: ['Car', 'IceCream'] as const,
}
// #= Products.Car | Products.IceCream
type X1 = Products.Registry[typeof carScream.names[number]]
// #= Products.Car & Products.IceCream
type X2 = UnionToIntersection<Products.Registry[typeof carScream.names[number]]>;
type MergedProduct<Names extends keyof Products.Registry> = Omit<
UnionToIntersection<Products.Registry[typeof carScream.names[number]]>,
'name' | 'names'
> & { names: UnionToTuple<Names> }
const carScream2: MergedProduct<'Car' | 'IceCream'> = {
names: ['Car', 'IceCream'],
drive() {
console.log('Vroom');
},
flavor: 'pistachio'
}
// Utils
export type UnionToIntersection<Union> =
(Union extends any
? (argument: Union) => void
: never
) extends (argument: infer Intersection) => void
? Intersection
: never;
type Overwrite<T, S extends any> = { [P in keyof T]: S[P] };
type TupleUnshift<T extends any[], X> = T extends any ? ((x: X, ...t: T) => void) extends (...t: infer R) => void ? R : never : never;
type TuplePush<T extends any[], X> = T extends any ? Overwrite<TupleUnshift<T, any>, T & { [x: string]: X }> : never;
type UnionToTuple<U> = UnionToTupleRecursively<[], U>;
type UnionToTupleRecursively<T extends any[], U> = {
1: T;
0: UnionToTupleRecursively_<T, U, U>;
}[[U] extends [never] ? 1 : 0]
type UnionToTupleRecursively_<T extends any[], U, S> =
S extends any ? UnionToTupleRecursively<TupleUnshift<T, S> | TuplePush<T, S>, Exclude<U, S>> : never;
let x: UnionToTuple<1 | 2 | 3 | 4> = [1, 2, 3, 4];
let y: UnionToTuple<1 | 2 | 3 | 4> = [4, 3, 2, 1];
@hasparus
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment