Last active
September 14, 2018 11:35
-
-
Save freddi301/600cb71e95e56ee28a459e00d90dfd81 to your computer and use it in GitHub Desktop.
TypeScript Utility Types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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