Skip to content

Instantly share code, notes, and snippets.

@Le0Michine
Last active May 20, 2018 02:54
Show Gist options
  • Save Le0Michine/395417fbf050ec8d8aca0721e32b575a to your computer and use it in GitHub Desktop.
Save Le0Michine/395417fbf050ec8d8aca0721e32b575a to your computer and use it in GitHub Desktop.
example demonstrating that in some cases inferred type could depend on the functions order in the code
interface Param {
name: string;
id?: number;
}
interface Result {
status: number;
}
type CallBack<T> = (result: T) => void;
interface OriginalApi1 {
fn(cb?: CallBack<Result>): string;
fn(p: Param, cb?: CallBack<Result>): string;
}
// Same as OriginalApi1 but with diffrent order of methods
interface OriginalApi2 {
fn(p: Param, cb?: CallBack<Result>): string;
fn(cb?: CallBack<Result>): string;
}
// Creates wrapper type which has methods with the same names as T returning Promise instead of using callbacks
type Wrapper<T> = { [K in keyof T]: T[K] extends (p: infer P1, cb?: (res: infer P2) => void) => infer R1 ? (p: P1) => Promise<P2> : never };
// Same as Wrapper, supposed to return never if P1 is a Function
type WrapperIgnoringOverloads<T> = { [K in keyof T]: T[K] extends (p: infer P1, cb?: (res: infer P2) => void) => infer R1 ? P1 extends Function ? never : (p: P1) => Promise<P2> : never };
let a: Wrapper<OriginalApi1>;
let b: Wrapper<OriginalApi2>;
a.fn({name: 'name'}); // OK, (property) fn: (p: Param) => Promise<Result>
b.fn({name: 'name'}); // Error, (property) fn: (p: CallBack<Result>) => Promise<Result>
let c: WrapperIgnoringOverloads<OriginalApi1>;
let d: WrapperIgnoringOverloads<OriginalApi2>;
c.fn({name: 'name'}); // OK, (property) fn: (p: Param) => Promise<Result>
d.fn({name: 'name'}); // Error, (property) fn: never
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment