Skip to content

Commit

Permalink
feat: callback 类型优化
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudcome committed May 12, 2023
1 parent 0ffc23d commit bd577c7
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 37 deletions.
43 changes: 28 additions & 15 deletions src/callbackCurry.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,48 @@
export type Callback<T> = (err: null | undefined | Error, res: T) => any;
export type Callback<T = void> = (err: null | undefined | void | Error, res: T) => any;

export type CallbackFunction0<T> = (callback: Callback<T>) => any;
export type CallbackFunction1<A, T> = (a: A, callback: Callback<T>) => any;
export type CallbackFunction2<A, B, T> = (a: A, b: B, callback: Callback<T>) => any;
export type CallbackFunction3<A, B, C, T> = (a: A, b: B, c: C, callback: Callback<T>) => any;
export type CallbackFunction4<A, B, C, D, T> = (a: A, b: B, c: C, d: D, callback: Callback<T>) => any;
export type CallbackFunction5<A, B, C, D, E, T> = (a: A, b: B, c: C, d: D, e: E, callback: Callback<T>) => any;
export type CallbackFunction6<A, B, C, D, E, F, T> = (a: A, b: B, c: C, d: D, e: E, f: F, callback: Callback<T>) => any;
export type CallbackFunction0<T = void> = (callback: Callback<T>) => any;
export type CallbackFunction1<A, T = void> = (a: A, callback: Callback<T>) => any;
export type CallbackFunction2<A, B, T = void> = (a: A, b: B, callback: Callback<T>) => any;
export type CallbackFunction3<A, B, C, T = void> = (a: A, b: B, c: C, callback: Callback<T>) => any;
export type CallbackFunction4<A, B, C, D, T = void> = (a: A, b: B, c: C, d: D, callback: Callback<T>) => any;
export type CallbackFunction5<A, B, C, D, E, T = void> = (a: A, b: B, c: C, d: D, e: E, callback: Callback<T>) => any;
export type CallbackFunction6<A, B, C, D, E, F, T = void> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
callback: Callback<T>
) => any;

export type CallbackCurried<T> = (callback: Callback<T>) => any;

export function callbackCurry<T>(cf: CallbackFunction0<T>): CallbackCurried<T>;
export function callbackCurry<A, T>(cf: CallbackFunction1<A, T>, a: A): CallbackCurried<T>;
export function callbackCurry<A, B, T>(cf: CallbackFunction2<A, B, T>, a: A, b: B): CallbackCurried<T>;
export function callbackCurry<A, B, C, T>(cf: CallbackFunction3<A, B, C, T>, a: A, b: B, c: C): CallbackCurried<T>;
export function callbackCurry<A, B, C, D, T>(
export function callbackCurry<T = void>(cf: CallbackFunction0<T>): CallbackCurried<T>;
export function callbackCurry<A, T = void>(cf: CallbackFunction1<A, T>, a: A): CallbackCurried<T>;
export function callbackCurry<A, B, T = void>(cf: CallbackFunction2<A, B, T>, a: A, b: B): CallbackCurried<T>;
export function callbackCurry<A, B, C, T = void>(
cf: CallbackFunction3<A, B, C, T>,
a: A,
b: B,
c: C
): CallbackCurried<T>;
export function callbackCurry<A, B, C, D, T = void>(
cf: CallbackFunction4<A, B, C, D, T>,
a: A,
b: B,
c: C,
d: D
): CallbackCurried<T>;
export function callbackCurry<A, B, C, D, E, T>(
export function callbackCurry<A, B, C, D, E, T = void>(
cf: CallbackFunction5<A, B, C, D, E, T>,
a: A,
b: B,
c: C,
d: D,
e: E
): CallbackCurried<T>;
export function callbackCurry<A, B, C, D, E, F, T>(
export function callbackCurry<A, B, C, D, E, F, T = void>(
cf: CallbackFunction6<A, B, C, D, E, F, T>,
a: A,
b: B,
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export { pkgName, pkgVersion } from './const';
export * from './const';
export * from './callbackCurry';
export * from './errorNormalize';
export * from './tryFunction';
export * from './tryCallback';
export * from './tryPromise';
export * from './tryFlatten';
export * from './types';
File renamed without changes.
24 changes: 15 additions & 9 deletions src/tryCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,34 @@ import type {
} from './callbackCurry';
import { callbackCurry } from './callbackCurry';
import { errorNormalize } from './errorNormalize';
import type { FlattenReturn } from './types/return';
import type { FlattenReturn } from './types';

export function tryCallback<T>(cf: CallbackFunction0<T>): Promise<FlattenReturn<T>>;
export function tryCallback<A, T>(cf: CallbackFunction1<A, T>, a: A): Promise<FlattenReturn<T>>;
export function tryCallback<A, B, T>(cf: CallbackFunction2<A, B, T>, a: A, b: B): Promise<FlattenReturn<T>>;
export function tryCallback<A, B, C, T>(cf: CallbackFunction3<A, B, C, T>, a: A, b: B, c: C): Promise<FlattenReturn<T>>;
export function tryCallback<A, B, C, D, T>(
cf: CallbackFunction4<A, B, C, D, T>,
export function tryCallback(cf: CallbackFunction0): Promise<FlattenReturn>;
export function tryCallback<T = void>(cf: CallbackFunction0<T>): Promise<FlattenReturn<T>>;
export function tryCallback<A, T = void>(cf: CallbackFunction1<A, T>, a: A): Promise<FlattenReturn<T>>;
export function tryCallback<A, B, T = void>(cf: CallbackFunction2<A, B, T>, a: A, b: B): Promise<FlattenReturn<T>>;
export function tryCallback<A, B, C, T = void>(
cf: CallbackFunction3<A, B, C, T>,
a: A,
b: B,
c: C
): Promise<FlattenReturn<T>>;
export function tryCallback<A, B, C, D, T = void>(
cf: CallbackFunction4<A, B, C, D>,
a: A,
b: B,
c: C,
d: D
): Promise<FlattenReturn<T>>;
export function tryCallback<A, B, C, D, E, T>(
export function tryCallback<A, B, C, D, E, T = void>(
cf: CallbackFunction5<A, B, C, D, E, T>,
a: A,
b: B,
c: C,
d: D,
e: E
): Promise<FlattenReturn<T>>;
export function tryCallback<A, B, C, D, E, F, T>(
export function tryCallback<A, B, C, D, E, F, T = void>(
cf: CallbackFunction6<A, B, C, D, E, F, T>,
a: A,
b: B,
Expand Down
2 changes: 1 addition & 1 deletion src/tryFlatten.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { CallbackFunction0 } from './callbackCurry';
import { tryCallback } from './tryCallback';
import { tryPromise } from './tryPromise';
import { tryFunction, type SyncFunction } from './tryFunction';
import type { FlattenReturn } from './types/return';
import type { FlattenReturn } from './types';

export type FlattenAble<T> = SyncFunction<T> | CallbackFunction0<T> | PromiseLike<T>;

Expand Down
2 changes: 1 addition & 1 deletion src/tryFunction.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { errorNormalize } from './errorNormalize';
import type { FlattenReturn } from './types/return';
import type { FlattenReturn } from './types';

export type SyncFunction<T> = () => T;

Expand Down
2 changes: 1 addition & 1 deletion src/tryPromise.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { errorNormalize } from './errorNormalize';
import type { FlattenReturn } from './types/return';
import type { FlattenReturn } from './types';

export function tryPromise<T>(promise: PromiseLike<T>): PromiseLike<FlattenReturn<T>> {
return promise.then(
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type FlattenReturn<T = void> = readonly [Error, undefined] | readonly [null, T];
1 change: 0 additions & 1 deletion src/types/return.d.ts

This file was deleted.

46 changes: 41 additions & 5 deletions test/callbackCurry.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { callbackCurry } from '../src/callbackCurry';
import type { Callback } from '../src/callbackCurry';
import { callbackCurry } from '../src';
import type { Callback } from '../src';
import { assertNumber } from './helpers';

test('0', () => {
test('0 input + 0 result', () => {
const cf = (cb: Callback) => {
cb(null);
};
const fn = vi.fn();
const cc = callbackCurry(cf);
cc((err, res) => {
fn(res);
});
expect(fn.mock.calls[0][0]).toBe(undefined);
});

test('0 input + 1 result', () => {
const cf = (cb: Callback<number>) => {
cb(null, 0);
};
Expand All @@ -15,7 +27,19 @@ test('0', () => {
expect(fn.mock.calls[0][0]).toBe(0);
});

test('1', async () => {
test('1 input + 0 result', async () => {
const cf = (a: string, cb: Callback) => {
cb();
};
const fn = vi.fn();
const cc = callbackCurry(cf, '');
cc((err) => {
fn();
});
expect(fn.mock.calls[0][0]).toBe(undefined);
});

test('1 input + 1 result', async () => {
const cf = (a: string, cb: Callback<number>) => {
cb(null, 0);
};
Expand All @@ -28,7 +52,19 @@ test('1', async () => {
expect(fn.mock.calls[0][0]).toBe(0);
});

test('', async () => {
test('2 input + 0 result', async () => {
const cf = (a: string, b: 'ba' | 'bb', cb: Callback) => {
cb(undefined);
};
const fn = vi.fn();
const cc = callbackCurry(cf, '', 'ba');
cc((err) => {
fn();
});
expect(fn.mock.calls[0][0]).toBe(undefined);
});

test('2 input + 1 result', async () => {
const cf = (a: string, b: 'ba' | 'bb', cb: Callback<number>) => {
cb(null, 0);
};
Expand Down
130 changes: 127 additions & 3 deletions test/tryCallback.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,47 @@ import type { CallbackFunction0, CallbackFunction1, CallbackFunction2 } from '..
import { tryCallback } from '../src';
import { assertError, assertNull, assertNumber, assertUndefined } from './helpers';

describe('tryCallbackFlatten 0', () => {
describe('tryCallbackFlatten 0 input + 0 result', () => {
test('resolved', async () => {
const callbackFunction = (callback: (err: Error | null) => void) => {
setTimeout(() => {
callback(null);
});
};
const [err, res] = await tryCallback(callbackFunction);

if (err) {
assertError(err);
} else {
assertNull(err);
}

expect(err).toBe(null);
expect(res).toBe(undefined);
});

test('rejected', async () => {
const callbackFunction = (callback: (err: Error | null) => void) => {
setTimeout(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
callback(new Error('1'));
});
};
const [err, res] = await tryCallback(callbackFunction);

if (err) {
assertError(err);
} else {
assertNull(err);
}

expect(err?.message).toBe('1');
expect(res).toBeUndefined();
});
});

describe('tryCallbackFlatten 0 input + 1 result', () => {
test('resolved', async () => {
const callbackFunction: CallbackFunction0<number> = (callback) => {
setTimeout(() => {
Expand Down Expand Up @@ -47,7 +87,49 @@ describe('tryCallbackFlatten 0', () => {
});
});

describe('tryCallbackFlatten 1', () => {
describe('tryCallbackFlatten 1 input + 0 result', () => {
test('resolved', async () => {
const callbackFunction: CallbackFunction1<string> = (a, callback) => {
setTimeout(() => {
callback(null);
});
};
const [err, res] = await tryCallback(callbackFunction, '');

if (err) {
assertError(err);
assertUndefined(res);
} else {
assertNull(err);
}

expect(err).toBe(null);
expect(res).toBeUndefined();
});

test('rejected', async () => {
const callbackFunction: CallbackFunction1<string> = (a, callback) => {
setTimeout(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
callback(new Error('1'));
});
};
const [err, res] = await tryCallback(callbackFunction, '');

if (err) {
assertError(err);
assertUndefined(res);
} else {
assertNull(err);
}

expect(err?.message).toBe('1');
expect(res).toBeUndefined();
});
});

describe('tryCallbackFlatten 1 input + 1 result', () => {
test('resolved', async () => {
const callbackFunction: CallbackFunction1<string, number> = (a, callback) => {
setTimeout(() => {
Expand Down Expand Up @@ -91,7 +173,49 @@ describe('tryCallbackFlatten 1', () => {
});
});

describe('tryCallbackFlatten 2', () => {
describe('tryCallbackFlatten 2 input + 0 result', () => {
test('resolved', async () => {
const callbackFunction = (a: string, b: 'b1' | 'b2', callback: (err: Error | null) => void) => {
setTimeout(() => {
callback(null);
});
};
const [err, res] = await tryCallback(callbackFunction, '', 'b1');

if (err) {
assertError(err);
assertUndefined(res);
} else {
assertNull(err);
}

expect(err).toBe(null);
expect(res).toBeUndefined();
});

test('rejected', async () => {
const callbackFunction = (a: string, b: 'b1' | 'b2', callback: (err: Error | null) => void) => {
setTimeout(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
callback(new Error('1'));
});
};
const [err, res] = await tryCallback(callbackFunction, '', 'b1');

if (err) {
assertError(err);
assertUndefined(res);
} else {
assertNull(err);
}

expect(err?.message).toBe('1');
expect(res).toBeUndefined();
});
});

describe('tryCallbackFlatten 2 input + 1 result', () => {
test('resolved', async () => {
const callbackFunction: CallbackFunction2<string, 'b1' | 'b2', number> = (a, b, callback) => {
setTimeout(() => {
Expand Down

0 comments on commit bd577c7

Please sign in to comment.