Skip to content

Instantly share code, notes, and snippets.

@freddi301
Last active September 14, 2018 11:35
Show Gist options
  • Save freddi301/600cb71e95e56ee28a459e00d90dfd81 to your computer and use it in GitHub Desktop.
Save freddi301/600cb71e95e56ee28a459e00d90dfd81 to your computer and use it in GitHub Desktop.
TypeScript Utility Types
type Diff<T, S extends Partial<T>> = { [P in Exclude<keyof T, keyof S>]: T[P] };
type CurryFunctionWithLabeledArguments<
Arguments,
Return,
Bound extends Partial<Arguments>,
Missing = Diff<Arguments, Bound>
> = Bound extends Arguments ? () => Return : CurriedFunctionWithLabeledArguments<Arguments, Return, Bound, Missing>;
interface CurriedFunctionWithLabeledArguments<Arguments, Return, Bound, Missing> {
<Added extends Partial<Missing>>(args: Added & Partial<Missing>): CurryFunctionWithLabeledArguments<
Arguments,
Return,
Bound & Added
>;
}
export function curryFunctionWithLabeledArguments<Arguments, Return, Bound = {}>(
fun: (args: Arguments) => Return,
bound?: Bound
): CurryFunctionWithLabeledArguments<Arguments, Return, Bound> {
return ((args: any) =>
args ? curryFunctionWithLabeledArguments(fun, { ...(bound as any), ...args }) : fun(bound as any)) as any;
}
// example
function abc(args: { a: string; b: number; c: boolean }) {
return new Date();
}
const f = curryFunctionWithLabeledArguments(abc);
const fab = f({ a: "", b: 0 });
const fabc = fab({ c: true });
const x = fabc();
export type Parameter1Type<Fun extends (...parameters: any[]) => any> = Fun extends (parameter1: infer Parameter1, ...parameters: any[]) => any ? Parameter1 : never;
export type Parameter2Type<Fun extends (...parameters: any[]) => any> = Fun extends (parameter1: any, parameter2: infer Parameter2, ...parameters: any[]) => any ? Parameter2 : never;
export type Parameter3Type<Fun extends (...parameters: any[]) => any> = Fun extends (parameter1: any, parameter2: any, parameter3: infer Parameter3, ...parameters: any[]) => any ? Parameter3 : never;
export type Parameter4Type<Fun extends (...parameters: any[]) => any> = Fun extends (parameter1: any, parameter2: any, parameter3: any, parameter4: infer Parameter4, ...parameters: any[]) => any ? Parameter4 : never;
export type Parameter5Type<Fun extends (...parameters: any[]) => any> = Fun extends (parameter1: any, parameter2: any, parameter3: any, parameter4: any, parameter5: infer Parameter5, ...parameters: any[]) => any ? Parameter5 : never;
export type Parameter6Type<Fun extends (...parameters: any[]) => any> = Fun extends (parameter1: any, parameter2: any, parameter3: any, parameter4: any, parameter5: any, parameter6: infer Parameter6, ...parameters: any[]) => any ? Parameter6 : never;
export type Parameter7Type<Fun extends (...parameters: any[]) => any> = Fun extends (parameter1: any, parameter2: any, parameter3: any, parameter4: any, parameter5: any, parameter6: any, parameter7: infer Parameter7, ...parameters: any[]) => any ? Parameter7 : never;
export type Parameter8Type<Fun extends (...parameters: any[]) => any> = Fun extends (parameter1: any, parameter2: any, parameter3: any, parameter4: any, parameter5: any, parameter6: any, parameter7: any, parameter8: infer Parameter8, ...parameters: any[]) => any ? Parameter8 : never;
function generateParameterOverloads(n: number) {
const params = Array.from(range(1, n));
return params.map(typeTemplate).join(";\n");
function typeTemplate(i: number) {
return `export type Parameter${i}Type<Fun extends (...parameters: any[]) => any> = Fun extends ${inferClause(
i
)} ? Parameter${i} : never`;
}
function inferClause(i: number) {
return `(${params
.slice(0, i - 1)
.map(anyParamter)
.concat([
`parameter${i}: infer Parameter${i}`,
`...parameters: any[]`
])
.join(", ")}) => any`;
}
function anyParamter(k: number) {
return `parameter${k}: any`;
}
}
function* range(start: number, end: number): IterableIterator<number> {
for (let i = start; i <= end; i++) {
yield i;
}
}
type Values<A extends {[index: string]: any}> = A extends {[index:string]: infer T } ? T : any
type Diff<T, S extends Partial<T>> = { [P in Exclude<keyof T, keyof S>]: T[P] };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment