Skip to content

Commit 24183a0

Browse files
Revert "Update: propEq to allow wider-typing for value in comparison (#74)"
This reverts commit ec00390.
1 parent f6b89e2 commit 24183a0

6 files changed

Lines changed: 47 additions & 318 deletions

File tree

test/allPass.test.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,3 @@ expectError(
4848
nickname: 'Blade'
4949
})
5050
);
51-
52-
const isQueen = propEq('Q', 'rank');
53-
const isSpade = propEq('♠︎', 'suit');
54-
const isQueenOfSpades = allPass([isQueen, isSpade]);
55-
56-
isQueenOfSpades({
57-
rank: '2',
58-
suit: '♠︎'
59-
});
60-
61-
const isQueen2 = (x: Record<'rank', string>) => x.rank === 'Q';
62-
const isSpade2 = (x: Record<'suit', string>) => x.suit === '♠︎';
63-
const isQueenOfSpades2 = allPass([isQueen2, isSpade2]);
64-
65-
isQueenOfSpades2({
66-
rank: '2',
67-
suit: '♠︎'
68-
});

test/anyPass.test.ts

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ expectType<boolean>(
2525
})
2626
);
2727

28-
expectType<boolean>(
28+
expectError(
2929
isVampire({
3030
age: 21,
3131
garlic_allergy: true,
3232
sun_allergy: true,
33-
fast: null,
34-
fear: undefined
33+
fast: false,
34+
fear: true
3535
})
3636
);
3737

@@ -48,26 +48,3 @@ expectError(
4848
nickname: 'Blade'
4949
})
5050
);
51-
52-
const isQueen = propEq('Q', 'rank');
53-
const isSpade = propEq('♠︎', 'suit');
54-
const isQueenOfSpades = anyPass([isQueen, isSpade]);
55-
56-
expectType<boolean>(isQueenOfSpades({
57-
rank: '2',
58-
suit: '♠︎'
59-
}));
60-
61-
expectError(isQueenOfSpades({
62-
rank: 2,
63-
suit: '♠︎'
64-
}));
65-
66-
const isQueen2 = (x: Record<'rank', string>) => x.rank === 'Q';
67-
const isSpade2 = (x: Record<'suit', string>) => x.suit === '♠︎';
68-
const isQueenOfSpades2 = anyPass([isQueen2, isSpade2]);
69-
70-
isQueenOfSpades2({
71-
rank: '2',
72-
suit: '♠︎'
73-
});

test/propEq.test.ts

Lines changed: 32 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -3,153 +3,37 @@ import { expectError, expectType } from 'tsd';
33
import { propEq } from '../es';
44

55
type Obj = {
6-
literals: 'A' | 'B';
7-
unions: number | string;
8-
nullable: number | null | undefined;
9-
optional?: number;
6+
union: 'foo' | 'bar';
7+
str: string;
8+
num: number;
9+
u: undefined;
10+
n: null;
1011
};
1112

12-
const obj = {} as Obj;
13-
14-
//
15-
// literals
16-
//
17-
18-
// happy path works as expected
19-
expectType<boolean>(propEq('A')('literals')(obj));
20-
expectType<boolean>(propEq('A', 'literals')(obj));
21-
expectType<boolean>(propEq('A', 'literals', obj));
22-
23-
// accepts any type that obj[key] can be widened too
24-
expectType<boolean>(propEq('C')('literals')(obj));
25-
expectType<boolean>(propEq('C', 'literals')(obj));
26-
// only propEq(val, key, obj) requests non-widened types
27-
expectError(propEq('C', 'literals', obj));
28-
29-
// rejects if type cannot be widened too
30-
expectError(propEq(2)('literals')(obj));
31-
expectError(propEq(2, 'literals')(obj));
32-
expectError(propEq(2, 'literals', obj));
33-
34-
// manually widened also works
35-
expectType<boolean>(propEq('A' as string)('literals')(obj));
36-
expectType<boolean>(propEq('A' as string, 'literals')(obj));
37-
// only rejects for propEq(val, key, obj), `string` is too wide for 'A' | 'B'
38-
expectError(propEq('A' as string, 'literals', obj));
39-
40-
// rejects if key is not on obj
41-
expectError(propEq('A')('literals')({} as Omit<Obj, 'literals'>));
42-
expectError(propEq('A', 'literals')({} as Omit<Obj, 'literals'>));
43-
expectError(propEq('A', 'literals', {} as Omit<Obj, 'literals'>));
44-
45-
// rejects empty object literal
46-
expectError(propEq('A')('literals')({}));
47-
expectError(propEq('A', 'literals')({}));
48-
expectError(propEq('A', 'literals', {}));
49-
50-
//
51-
// unions
52-
//
53-
54-
// happy path works as expected
55-
expectType<boolean>(propEq('1')('unions')(obj));
56-
expectType<boolean>(propEq('1', 'unions')(obj));
57-
expectType<boolean>(propEq('1', 'unions', obj));
58-
59-
expectType<boolean>(propEq(1)('unions')(obj));
60-
expectType<boolean>(propEq(1, 'unions')(obj));
61-
expectType<boolean>(propEq(1, 'unions', obj));
62-
63-
// rejects if typeof val not part of union type
64-
expectError(propEq(true)('unions')(obj));
65-
expectError(propEq(true, 'unions')(obj));
66-
expectError(propEq(true, 'unions', obj));
67-
68-
// rejects if key is not on obj
69-
expectError(propEq('1')('unions')({} as Omit<Obj, 'unions'>));
70-
expectError(propEq('1', 'unions')({} as Omit<Obj, 'unions'>));
71-
expectError(propEq('1', 'unions', {} as Omit<Obj, 'unions'>));
72-
73-
// rejects empty object literal
74-
expectError(propEq('1')('unions')({}));
75-
expectError(propEq('1', 'unions')({}));
76-
expectError(propEq('1', 'unions', {}));
77-
78-
//
79-
// nullable
80-
//
81-
82-
// happy path works as expected
83-
expectType<boolean>(propEq(1)('nullable')(obj));
84-
expectType<boolean>(propEq(1, 'nullable')(obj));
85-
expectType<boolean>(propEq(1, 'nullable', obj));
86-
87-
expectType<boolean>(propEq(null)('nullable')(obj));
88-
expectType<boolean>(propEq(null, 'nullable')(obj));
89-
expectType<boolean>(propEq(null, 'nullable', obj));
90-
91-
expectType<boolean>(propEq(undefined)('nullable')(obj));
92-
expectType<boolean>(propEq(undefined, 'nullable')(obj));
93-
expectType<boolean>(propEq(undefined, 'nullable', obj));
94-
95-
// rejects if typeof val not part of union type
96-
expectError(propEq(true)('nullable')(obj));
97-
expectError(propEq(true, 'nullable')(obj));
98-
expectError(propEq(true, 'nullable', obj));
99-
100-
// rejects if key is not on obj
101-
expectError(propEq(1)('nullable')({} as Omit<Obj, 'nullable'>));
102-
expectError(propEq(1, 'nullable')({} as Omit<Obj, 'nullable'>));
103-
expectError(propEq(1, 'nullable', {} as Omit<Obj, 'nullable'>));
104-
105-
// rejects empty object literal
106-
expectError(propEq(1)('nullable')({}));
107-
expectError(propEq(1, 'nullable')({}));
108-
expectError(propEq(1, 'nullable', {}));
109-
110-
//
111-
// optional
112-
//
113-
114-
// happy path works as expected
115-
expectType<boolean>(propEq(1)('optional')(obj));
116-
expectType<boolean>(propEq(1, 'optional')(obj));
117-
expectType<boolean>(propEq(1, 'optional', obj));
118-
119-
expectType<boolean>(propEq(undefined)('optional')(obj));
120-
expectType<boolean>(propEq(undefined, 'optional')(obj));
121-
expectType<boolean>(propEq(undefined, 'optional', obj));
122-
123-
// `null` produces error for `optional`. this is expected because typescript strictNullCheck `null !== undefined`
124-
expectError(propEq(null)('optional')(obj));
125-
expectError(propEq(null, 'optional')(obj));
126-
expectError(propEq(null, 'optional', obj));
127-
128-
// rejects if typeof val not part of union type
129-
expectError(propEq(true)('optional')(obj));
130-
expectError(propEq(true, 'optional')(obj));
131-
expectError(propEq(true, 'optional', obj));
132-
133-
// rejects if key is not on obj
134-
expectError(propEq(1)('optional')({} as Omit<Obj, 'optional'>));
135-
expectError(propEq(1, 'optional')({} as Omit<Obj, 'optional'>));
136-
expectError(propEq(1, 'optional', {} as Omit<Obj, 'optional'>));
137-
138-
// rejects empty object literal literal
139-
expectError(propEq(1)('optional')({}));
140-
expectError(propEq(1, 'optional')({}));
141-
expectError(propEq(1, 'optional', {}));
142-
143-
//
144-
// other non-happy paths
145-
//
146-
147-
// rejects unknown key
148-
expectError(propEq(1)('whatever')(obj));
149-
expectError(propEq(1, 'whatever')(obj));
150-
expectError(propEq(1, 'whatever', obj));
151-
152-
// rejects unknown key on emptyu object literal
153-
expectError(propEq(1)('whatever')({}));
154-
expectError(propEq(1, 'whatever')({}));
155-
expectError(propEq(1, 'whatever', {}));
13+
// propEq(val, name, obj)
14+
expectType<boolean>(propEq('foo', 'union', {} as Obj));
15+
// non-union string fails
16+
expectError(propEq('nope', 'union', {} as Obj));
17+
// completely different type fails
18+
expectError(propEq(2, 'union', {} as Obj));
19+
20+
// propEq(val)(name)(obj)
21+
expectType<boolean>(propEq('foo')('union')({} as Obj));
22+
// 'nope' is inferred as 'string' here.
23+
expectType<boolean>(propEq('nope')('union')({} as Obj));
24+
// completely different type fails
25+
expectError(propEq(2)('union')({} as Obj));
26+
27+
// propEq(val)(name), obj)
28+
expectType<boolean>(propEq('foo')('union', {} as Obj));
29+
// 'nope' is inferred as 'string' here.
30+
expectType<boolean>(propEq('nope')('union', {} as Obj));
31+
// completely different type fails
32+
expectError(propEq(2)('union', {} as Obj));
33+
34+
// propEq(val, name)(obj)
35+
expectType<boolean>(propEq('foo', 'union')({} as Obj));
36+
// 'nope' is inferred as 'string' here.
37+
expectType<boolean>(propEq('nope', 'union')({} as Obj));
38+
// completely different type fails
39+
expectError(propEq(2, 'union')({} as Obj));

types/allPass.d.ts

Lines changed: 3 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
1-
// narrowing
21
export function allPass<T, TF1 extends T, TF2 extends T>(
3-
predicates: [
4-
(a: T) => a is TF1,
5-
(a: T) => a is TF2
6-
]
2+
predicates: [(a: T) => a is TF1, (a: T) => a is TF2]
73
): (a: T) => a is TF1 & TF2;
84
export function allPass<T, TF1 extends T, TF2 extends T, TF3 extends T>(
9-
predicates: [
10-
(a: T) => a is TF1,
11-
(a: T) => a is TF2,
12-
(a: T) => a is TF3
13-
],
5+
predicates: [(a: T) => a is TF1, (a: T) => a is TF2, (a: T) => a is TF3],
146
): (a: T) => a is TF1 & TF2 & TF3;
157
export function allPass<T, TF1 extends T, TF2 extends T, TF3 extends T, TF4 extends T>(
16-
predicates: [
17-
(a: T) => a is TF1,
18-
(a: T) => a is TF2,
19-
(a: T) => a is TF3,
20-
(a: T) => a is TF4
21-
],
8+
predicates: [(a: T) => a is TF1, (a: T) => a is TF2, (a: T) => a is TF3, (a: T) => a is TF4],
229
): (a: T) => a is TF1 & TF2 & TF3 & TF4;
2310
export function allPass<T, TF1 extends T, TF2 extends T, TF3 extends T, TF4 extends T, TF5 extends T>(
2411
predicates: [
@@ -39,46 +26,4 @@ export function allPass<T, TF1 extends T, TF2 extends T, TF3 extends T, TF4 exte
3926
(a: T) => a is TF6
4027
],
4128
): (a: T) => a is TF1 & TF2 & TF3 & TF4 & TF5 & TF6;
42-
// regular
43-
export function allPass<T1, T2>(
44-
predicates: [
45-
(a: T1) => boolean,
46-
(a: T2) => boolean
47-
],
48-
): (a: T1 & T2) => boolean;
49-
export function allPass<T1, T2, T3>(
50-
predicates: [
51-
(a: T1) => boolean,
52-
(a: T2) => boolean,
53-
(a: T3) => boolean
54-
],
55-
): (a: T1 & T2 & T3) => boolean;
56-
export function allPass<T1, T2, T3, T4>(
57-
predicates: [
58-
(a: T1) => boolean,
59-
(a: T2) => boolean,
60-
(a: T3) => boolean,
61-
(a: T4) => boolean
62-
],
63-
): (a: T1 & T2 & T3 & T4) => boolean;
64-
export function allPass<T1, T2, T3, T4, T5>(
65-
predicates: [
66-
(a: T1) => boolean,
67-
(a: T2) => boolean,
68-
(a: T3) => boolean,
69-
(a: T4) => boolean,
70-
(a: T5) => boolean
71-
],
72-
): (a: T1 & T2 & T3 & T4 & T5) => boolean;
73-
export function allPass<T1, T2, T3, T4, T5, T6>(
74-
predicates: [
75-
(a: T1) => boolean,
76-
(a: T2) => boolean,
77-
(a: T3) => boolean,
78-
(a: T4) => boolean,
79-
(a: T5) => boolean,
80-
(a: T6) => boolean
81-
],
82-
): (a: T1 & T2 & T3 & T4 & T5 & T6) => boolean;
83-
// catch-all
8429
export function allPass<F extends (...args: any[]) => boolean>(predicates: readonly F[]): F;

0 commit comments

Comments
 (0)