Skip to content

Commit a891143

Browse files
authored
Every: Fix behavior when the target type is never (#1163)
1 parent 42d6106 commit a891143

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

source/internal/array.d.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type {If} from '../if.d.ts';
2+
import type {IsAny} from '../is-any.d.ts';
23
import type {IsNever} from '../is-never.d.ts';
34
import type {UnknownArray} from '../unknown-array.d.ts';
5+
import type {IfNotAnyOrNever} from './type.d.ts';
46

57
/**
68
Infer the length of the given array `<T>`.
@@ -99,7 +101,7 @@ Returns a boolean for whether every element in an array type extends another typ
99101
100102
Note:
101103
- This type is not designed to be used with non-tuple arrays (like `number[]`), tuples with optional elements (like `[1?, 2?, 3?]`), or tuples that contain a rest element (like `[1, 2, ...number[]]`).
102-
- The `never` type does not match the target type unless the target type itself is `never`. For example, `Every<[never, never], never>` returns `true`, but `Every<[never, number], number>` returns `false`.
104+
- The `never` type does not match the target type unless the target type is `never` or `any`. For example, `Every<[never, never], never>` returns `true`, but `Every<[never, number], number>` returns `false`.
103105
104106
@example
105107
```
@@ -118,10 +120,14 @@ type D = Every<[true, boolean, true], true>;
118120
//=> boolean
119121
```
120122
*/
121-
export type Every<TArray extends UnknownArray, Type> = TArray extends readonly [infer First, ...infer Rest]
122-
? IsNever<First> extends true
123-
? IsNever<Type>
124-
: First extends Type
125-
? Every<Rest, Type>
126-
: false
127-
: true;
123+
export type Every<TArray extends UnknownArray, Type> = IfNotAnyOrNever<TArray, If<IsAny<Type>, true,
124+
TArray extends readonly [infer First, ...infer Rest]
125+
? IsNever<First> extends true
126+
? IsNever<Type> extends true
127+
? Every<Rest, Type>
128+
: false
129+
: First extends Type
130+
? Every<Rest, Type>
131+
: false
132+
: true
133+
>, false, false>;

test-d/internal/every.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,17 @@ expectType<Every<[true, false] | [true, boolean], true>>({} as boolean); // One
3333
// Boundary cases
3434
expectType<Every<[], any>>(true);
3535
expectType<Every<[], never>>(true);
36-
expectType<Every<[1, 2, '3', true, false, string[]], any>>(true);
36+
expectType<Every<[1, 2, '3', true, false, string[], never], any>>(true);
3737
expectType<Every<[any, any], any>>(true);
38+
expectType<Every<[never, never], any>>(true);
3839
expectType<Every<[1, 2], never>>(false);
3940
expectType<Every<[never, never], never>>(true);
41+
expectType<Every<[never, never, number], never>>(false);
42+
expectType<Every<[number, never, never], never>>(false);
43+
expectType<Every<[never, number, never, any, never], never>>(false);
44+
expectType<Every<[never, any, never, any], never>>({} as boolean);
4045
expectType<Every<[1, 2, any], number>>({} as boolean);
4146
expectType<Every<[1, 2, never], number>>(false);
47+
48+
expectType<Every<any, never>>(false);
49+
expectType<Every<never, any>>(false);

0 commit comments

Comments
 (0)