varianter
Version:
Simple variants/tagged unions/discriminated unions in TypeScript
41 lines (40 loc) • 1.61 kB
TypeScript
declare type Expand<T> = T extends infer O ? {
[K in keyof O]: O[K];
} : never;
declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
export declare type UnionToVariantMap<U extends {
[key: string]: any;
}, C extends keyof U> = Expand<UnionToIntersection<U extends any ? {
[K in U[C]]: Expand<Omit<U, C>>;
} : never>>;
declare type VariantMap = {
[key: string]: any;
};
declare type MapVariantMap<T extends VariantMap> = {
[K in keyof T]: (data: T[K]) => any;
};
declare type VariantData<T extends VariantMap> = Expand<{
[K in keyof T]: T[K] extends undefined ? never : T[K];
}[keyof T]>;
declare type MapVariantMapLike<T extends VariantMap> = MapVariantMap<T> | (Partial<MapVariantMap<T>> & {
_: (data: VariantData<T>) => any;
});
declare type MapVariant<T extends VariantMap> = <M extends MapVariantMapLike<T>>(map: M) => {
[K in keyof M]: M[K] extends (...args: any) => any ? ReturnType<M[K]> : never;
}[keyof M];
declare type VariantMethods<T extends VariantMap> = {
map: MapVariant<T>;
};
declare type VariantCreatorMap<T extends VariantMap> = {
[K in keyof T]: [T[K]] extends [never] ? () => Expand<{
type: K;
} & VariantMethods<T>> : (data: T[K]) => Expand<{
type: K;
data: T[K];
} & VariantMethods<T>>;
};
export declare const createVariant: <T extends VariantMap>() => VariantCreatorMap<T>;
export declare type Member<T extends VariantCreatorMap<any>> = Expand<{
[K in keyof T]: ReturnType<T[K]>;
}[keyof T]>;
export {};