Skip to content

Commit 0b44c4c

Browse files
committed
Use overloads for more accurate types
1 parent 456e5b5 commit 0b44c4c

15 files changed

+304
-12
lines changed

src/every.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,41 @@ describe('asyncEvery()', () => {
115115

116116
await expect(() => asyncEvery(inputArr, mapper)).rejects.toThrow('Some error');
117117
});
118+
119+
it('returns type boolean given function that returns type Promise<boolean>', async () => {
120+
// @ts-expect-no-error
121+
const result: boolean = await asyncEvery(inputArr, largerOrEqualThanZeroInRandomTime);
122+
123+
expect(typeof result).toBe('boolean');
124+
});
125+
126+
it('returns type true given function that returns type Promise<true>', async () => {
127+
async function trueInRandomTime() {
128+
return new Promise<true>((resolve) =>
129+
setTimeout(() => {
130+
resolve(true);
131+
}, Math.random() * 100),
132+
);
133+
}
134+
135+
// @ts-expect-no-error
136+
const result: true = await asyncEvery(inputArr, trueInRandomTime);
137+
138+
expect(result).toBe(true);
139+
});
140+
141+
it('returns type false given function that returns type Promise<false>', async () => {
142+
async function falseInRandomTime() {
143+
return new Promise<false>((resolve) =>
144+
setTimeout(() => {
145+
resolve(false);
146+
}, Math.random() * 100),
147+
);
148+
}
149+
150+
// @ts-expect-no-error
151+
const result: false = await asyncEvery(inputArr, falseInRandomTime);
152+
153+
expect(result).toBe(false);
154+
});
118155
});

src/every.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
import asyncForEach from './forEach';
22

3-
export default function asyncEvery<T>(
3+
function asyncEvery<T>(
4+
arr: T[],
5+
fn: (cur: T, idx: number, arr: T[]) => Promise<true>,
6+
): Promise<true>;
7+
function asyncEvery<T>(
8+
arr: T[],
9+
fn: (cur: T, idx: number, arr: T[]) => Promise<false>,
10+
): Promise<false>;
11+
function asyncEvery<T>(
12+
arr: T[],
13+
fn: (cur: T, idx: number, arr: T[]) => Promise<boolean>,
14+
): Promise<boolean>;
15+
function asyncEvery<T>(
416
arr: T[],
517
fn: (cur: T, idx: number, arr: T[]) => Promise<boolean>,
618
): Promise<boolean> {
@@ -34,3 +46,5 @@ export default function asyncEvery<T>(
3446
});
3547
});
3648
}
49+
50+
export default asyncEvery;

src/every_strict.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,41 @@ describe('asyncEveryStrict()', () => {
150150

151151
await expect(() => asyncEveryStrict(inputArr, mapper)).rejects.toThrow('Some error');
152152
});
153+
154+
it('returns type boolean given function that returns type Promise<boolean>', async () => {
155+
// @ts-expect-no-error
156+
const result: boolean = await asyncEveryStrict(inputArr, largerOrEqualThanZeroInRandomTime);
157+
158+
expect(typeof result).toBe('boolean');
159+
});
160+
161+
it('returns type true given function that returns type Promise<true>', async () => {
162+
async function trueInRandomTime() {
163+
return new Promise<true>((resolve) =>
164+
setTimeout(() => {
165+
resolve(true);
166+
}, Math.random() * 100),
167+
);
168+
}
169+
170+
// @ts-expect-no-error
171+
const result: true = await asyncEveryStrict(inputArr, trueInRandomTime);
172+
173+
expect(result).toBe(true);
174+
});
175+
176+
it('returns type false given function that returns type Promise<false>', async () => {
177+
async function falseInRandomTime() {
178+
return new Promise<false>((resolve) =>
179+
setTimeout(() => {
180+
resolve(false);
181+
}, Math.random() * 100),
182+
);
183+
}
184+
185+
// @ts-expect-no-error
186+
const result: false = await asyncEveryStrict(inputArr, falseInRandomTime);
187+
188+
expect(result).toBe(false);
189+
});
153190
});

src/every_strict.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
import asyncForEachStrict from './forEach_strict';
22

3-
export default function asyncEveryStrict<T>(
3+
function asyncEveryStrict<T>(
4+
arr: T[],
5+
fn: (cur: T, idx: number, arr: T[]) => Promise<true>,
6+
): Promise<true>;
7+
function asyncEveryStrict<T>(
8+
arr: T[],
9+
fn: (cur: T, idx: number, arr: T[]) => Promise<false>,
10+
): Promise<false>;
11+
function asyncEveryStrict<T>(
12+
arr: T[],
13+
fn: (cur: T, idx: number, arr: T[]) => Promise<boolean>,
14+
): Promise<boolean>;
15+
function asyncEveryStrict<T>(
416
arr: T[],
517
fn: (cur: T, idx: number, arr: T[]) => Promise<boolean>,
618
): Promise<boolean> {
@@ -34,3 +46,5 @@ export default function asyncEveryStrict<T>(
3446
});
3547
});
3648
}
49+
50+
export default asyncEveryStrict;

src/filter.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,22 @@ describe('asyncFilter()', () => {
8787

8888
await expect(() => asyncFilter(inputArr, mapper)).rejects.toThrow('Some error');
8989
});
90+
91+
it('returns type T[] given function that returns type Promise<boolean>', async () => {
92+
// @ts-expect-no-error
93+
const result: number[] = await asyncFilter(inputArr, largerThanTwoInRandomTime);
94+
});
95+
96+
it('returns type never[] given function that returns type Promise<false>', async () => {
97+
async function falseInRandomTime() {
98+
return new Promise<false>((resolve) =>
99+
setTimeout(() => {
100+
resolve(false);
101+
}, Math.random() * 100),
102+
);
103+
}
104+
105+
// @ts-expect-no-error
106+
const result: never[] = await asyncFilter(inputArr, falseInRandomTime);
107+
});
90108
});

src/filter.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
import asyncForEach from './forEach';
22

3-
export default function asyncFilter<T>(
3+
function asyncFilter<T>(
4+
arr: T[],
5+
fn: (cur: T, idx: number, arr: T[]) => Promise<false>,
6+
): Promise<never[]>;
7+
function asyncFilter<T>(
8+
arr: T[],
9+
fn: (cur: T, idx: number, arr: T[]) => Promise<boolean>,
10+
): Promise<T[]>;
11+
function asyncFilter<T>(
412
arr: T[],
513
fn: (cur: T, idx: number, arr: T[]) => Promise<boolean>,
6-
): Promise<T[]> {
14+
): Promise<T[] | never[]> {
715
const result: T[] = [];
816

917
return asyncForEach<T, void>(
@@ -21,3 +29,5 @@ export default function asyncFilter<T>(
2129
}),
2230
).then(() => result.filter((cur, idx) => idx in result));
2331
}
32+
33+
export default asyncFilter;

src/filter_strict.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,22 @@ describe('asyncFilterStrict()', () => {
116116

117117
await expect(() => asyncFilterStrict(inputArr, mapper)).rejects.toThrow('Some error');
118118
});
119+
120+
it('returns type T[] given function that returns type Promise<boolean>', async () => {
121+
// @ts-expect-no-error
122+
const result: number[] = await asyncFilterStrict(inputArr, largerThanTwoInRandomTime);
123+
});
124+
125+
it('returns type never[] given function that returns type Promise<false>', async () => {
126+
async function falseInRandomTime() {
127+
return new Promise<false>((resolve) =>
128+
setTimeout(() => {
129+
resolve(false);
130+
}, Math.random() * 100),
131+
);
132+
}
133+
134+
// @ts-expect-no-error
135+
const result: never[] = await asyncFilterStrict(inputArr, falseInRandomTime);
136+
});
119137
});

src/filter_strict.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
import asyncForEachStrict from './forEach_strict';
22

3-
export default function asyncFilterStrict<T>(
3+
function asyncFilterStrict<T>(
4+
arr: T[],
5+
fn: (cur: T, idx: number, arr: T[]) => Promise<false>,
6+
): Promise<never[]>;
7+
function asyncFilterStrict<T>(
8+
arr: T[],
9+
fn: (cur: T, idx: number, arr: T[]) => Promise<boolean>,
10+
): Promise<T[]>;
11+
function asyncFilterStrict<T>(
412
arr: T[],
513
fn: (cur: T, idx: number, arr: T[]) => Promise<boolean>,
6-
): Promise<T[]> {
14+
): Promise<T[] | never[]> {
715
const result: T[] = [];
816

917
return asyncForEachStrict<T, void>(
@@ -21,3 +29,5 @@ export default function asyncFilterStrict<T>(
2129
}),
2230
).then(() => result.filter((cur, idx) => idx in result));
2331
}
32+
33+
export default asyncFilterStrict;

src/map.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,19 @@ describe('asyncMap()', () => {
8888

8989
await expect(() => asyncMap(inputArr, mapper)).rejects.toThrow('Some error');
9090
});
91+
92+
it('returns type true[] given function that returns type Promise<true>', async () => {
93+
async function stringInRandomTime() {
94+
return new Promise<string>((resolve) =>
95+
setTimeout(() => {
96+
resolve('foo');
97+
}, Math.random() * 100),
98+
);
99+
}
100+
101+
// @ts-expect-no-error
102+
const result: string[] = await asyncMap([1, 2, 3], stringInRandomTime);
103+
104+
expect(result).toEqual(['foo', 'foo', 'foo']);
105+
});
91106
});

src/map_strict.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,19 @@ describe('asyncMapStrict()', () => {
116116

117117
await expect(() => asyncMapStrict(inputArr, mapper)).rejects.toThrow('Some error');
118118
});
119+
120+
it('returns type true[] given function that returns type Promise<true>', async () => {
121+
async function stringInRandomTime() {
122+
return new Promise<string>((resolve) =>
123+
setTimeout(() => {
124+
resolve('foo');
125+
}, Math.random() * 100),
126+
);
127+
}
128+
129+
// @ts-expect-no-error
130+
const result: string[] = await asyncMapStrict([1, 2, 3], stringInRandomTime);
131+
132+
expect(result).toEqual(['foo', 'foo', 'foo']);
133+
});
119134
});

0 commit comments

Comments
 (0)