Skip to content

Add a type-guard overload of Array.every #38200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/lib/es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,15 @@ interface ReadonlyArray<T> {
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
*/
lastIndexOf(searchElement: T, fromIndex?: number): number;
/**
* Determines whether all the members of an array satisfy the specified test.
* @param callbackfn A function that accepts up to three arguments. The every method calls
* the callbackfn function for each element in the array until the callbackfn returns a value
* which is coercible to the Boolean value false, or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every<S extends T>(callbackfn: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): this is readonly S[];
/**
* Determines whether all the members of an array satisfy the specified test.
* @param callbackfn A function that accepts up to three arguments. The every method calls
Expand Down Expand Up @@ -1279,6 +1288,15 @@ interface Array<T> {
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
*/
lastIndexOf(searchElement: T, fromIndex?: number): number;
/**
* Determines whether all the members of an array satisfy the specified test.
* @param callbackfn A function that accepts up to three arguments. The every method calls
* the callbackfn function for each element in the array until the callbackfn returns a value
* which is coercible to the Boolean value false, or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[];
/**
* Determines whether all the members of an array satisfy the specified test.
* @param callbackfn A function that accepts up to three arguments. The every method calls
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/2dArrays.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ class Board {
>allShipsSunk : Symbol(Board.allShipsSunk, Decl(2dArrays.ts, 9, 18))

return this.ships.every(function (val) { return val.isSunk; });
>this.ships.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>this.ships.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>this.ships : Symbol(Board.ships, Decl(2dArrays.ts, 7, 13))
>this : Symbol(Board, Decl(2dArrays.ts, 5, 1))
>ships : Symbol(Board.ships, Decl(2dArrays.ts, 7, 13))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>val : Symbol(val, Decl(2dArrays.ts, 12, 42))
>val.isSunk : Symbol(Ship.isSunk, Decl(2dArrays.ts, 3, 12))
>val : Symbol(val, Decl(2dArrays.ts, 12, 42))
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/2dArrays.types
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ class Board {

return this.ships.every(function (val) { return val.isSunk; });
>this.ships.every(function (val) { return val.isSunk; }) : boolean
>this.ships.every : (callbackfn: (value: Ship, index: number, array: Ship[]) => unknown, thisArg?: any) => boolean
>this.ships.every : { <S extends Ship>(callbackfn: (value: Ship, index: number, array: Ship[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: Ship, index: number, array: Ship[]) => unknown, thisArg?: any): boolean; }
>this.ships : Ship[]
>this : this
>ships : Ship[]
>every : (callbackfn: (value: Ship, index: number, array: Ship[]) => unknown, thisArg?: any) => boolean
>every : { <S extends Ship>(callbackfn: (value: Ship, index: number, array: Ship[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: Ship, index: number, array: Ship[]) => unknown, thisArg?: any): boolean; }
>function (val) { return val.isSunk; } : (val: Ship) => boolean
>val : Ship
>val.isSunk : boolean
Expand Down
16 changes: 16 additions & 0 deletions tests/baselines/reference/arrayEvery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//// [arrayEvery.ts]
const foo: (number | string)[] = ['aaa'];

const isString = (x: unknown): x is string => typeof x === 'string';

if (foo.every(isString)) {
foo[0].slice(0);
}


//// [arrayEvery.js]
var foo = ['aaa'];
var isString = function (x) { return typeof x === 'string'; };
if (foo.every(isString)) {
foo[0].slice(0);
}
22 changes: 22 additions & 0 deletions tests/baselines/reference/arrayEvery.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
=== tests/cases/compiler/arrayEvery.ts ===
const foo: (number | string)[] = ['aaa'];
>foo : Symbol(foo, Decl(arrayEvery.ts, 0, 5))

const isString = (x: unknown): x is string => typeof x === 'string';
>isString : Symbol(isString, Decl(arrayEvery.ts, 2, 5))
>x : Symbol(x, Decl(arrayEvery.ts, 2, 18))
>x : Symbol(x, Decl(arrayEvery.ts, 2, 18))
>x : Symbol(x, Decl(arrayEvery.ts, 2, 18))

if (foo.every(isString)) {
>foo.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>foo : Symbol(foo, Decl(arrayEvery.ts, 0, 5))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>isString : Symbol(isString, Decl(arrayEvery.ts, 2, 5))

foo[0].slice(0);
>foo[0].slice : Symbol(String.slice, Decl(lib.es5.d.ts, --, --))
>foo : Symbol(foo, Decl(arrayEvery.ts, 0, 5))
>slice : Symbol(String.slice, Decl(lib.es5.d.ts, --, --))
}

32 changes: 32 additions & 0 deletions tests/baselines/reference/arrayEvery.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
=== tests/cases/compiler/arrayEvery.ts ===
const foo: (number | string)[] = ['aaa'];
>foo : (string | number)[]
>['aaa'] : string[]
>'aaa' : "aaa"

const isString = (x: unknown): x is string => typeof x === 'string';
>isString : (x: unknown) => x is string
>(x: unknown): x is string => typeof x === 'string' : (x: unknown) => x is string
>x : unknown
>typeof x === 'string' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>'string' : "string"

if (foo.every(isString)) {
>foo.every(isString) : boolean
>foo.every : { <S extends string | number>(callbackfn: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; }
>foo : (string | number)[]
>every : { <S extends string | number>(callbackfn: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; }
>isString : (x: unknown) => x is string

foo[0].slice(0);
>foo[0].slice(0) : string
>foo[0].slice : (start?: number, end?: number) => string
>foo[0] : string
>foo : string[]
>0 : 0
>slice : (start?: number, end?: number) => string
>0 : 0
}

8 changes: 4 additions & 4 deletions tests/baselines/reference/contextuallyTypedIife.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@
// rest parameters
((...numbers) => numbers.every(n => n > 0))(5,6,7);
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 17, 2))
>numbers.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>numbers.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>numbers : Symbol(numbers, Decl(contextuallyTypedIife.ts, 17, 2))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 31))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 17, 31))

((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
>mixed : Symbol(mixed, Decl(contextuallyTypedIife.ts, 18, 2))
>mixed.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>mixed.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>mixed : Symbol(mixed, Decl(contextuallyTypedIife.ts, 18, 2))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 27))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 18, 27))

Expand Down
8 changes: 4 additions & 4 deletions tests/baselines/reference/contextuallyTypedIife.types
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@
>(...numbers) => numbers.every(n => n > 0) : (numbers_0: number, numbers_1: number, numbers_2: number) => boolean
>numbers : [number, number, number]
>numbers.every(n => n > 0) : boolean
>numbers.every : (callbackfn: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean
>numbers.every : { <S extends number>(callbackfn: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }
>numbers : [number, number, number]
>every : (callbackfn: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean
>every : { <S extends number>(callbackfn: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }
>n => n > 0 : (n: number) => boolean
>n : number
>n > 0 : boolean
Expand All @@ -123,9 +123,9 @@
>(...mixed) => mixed.every(n => !!n) : (mixed_0: number, mixed_1: string, mixed_2: string) => boolean
>mixed : [number, string, string]
>mixed.every(n => !!n) : boolean
>mixed.every : (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any) => boolean
>mixed.every : { <S extends string | number>(callbackfn: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; }
>mixed : [number, string, string]
>every : (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any) => boolean
>every : { <S extends string | number>(callbackfn: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; }
>n => !!n : (n: string | number) => boolean
>n : string | number
>!!n : boolean
Expand Down
8 changes: 4 additions & 4 deletions tests/baselines/reference/contextuallyTypedIifeStrict.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@
// rest parameters
((...numbers) => numbers.every(n => n > 0))(5,6,7);
>numbers : Symbol(numbers, Decl(contextuallyTypedIifeStrict.ts, 17, 2))
>numbers.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>numbers.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>numbers : Symbol(numbers, Decl(contextuallyTypedIifeStrict.ts, 17, 2))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 17, 31))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 17, 31))

((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
>mixed : Symbol(mixed, Decl(contextuallyTypedIifeStrict.ts, 18, 2))
>mixed.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>mixed.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>mixed : Symbol(mixed, Decl(contextuallyTypedIifeStrict.ts, 18, 2))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 18, 27))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 18, 27))

Expand Down
8 changes: 4 additions & 4 deletions tests/baselines/reference/contextuallyTypedIifeStrict.types
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@
>(...numbers) => numbers.every(n => n > 0) : (numbers_0: number, numbers_1: number, numbers_2: number) => boolean
>numbers : [number, number, number]
>numbers.every(n => n > 0) : boolean
>numbers.every : (callbackfn: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean
>numbers.every : { <S extends number>(callbackfn: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }
>numbers : [number, number, number]
>every : (callbackfn: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean
>every : { <S extends number>(callbackfn: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }
>n => n > 0 : (n: number) => boolean
>n : number
>n > 0 : boolean
Expand All @@ -123,9 +123,9 @@
>(...mixed) => mixed.every(n => !!n) : (mixed_0: number, mixed_1: string, mixed_2: string) => boolean
>mixed : [number, string, string]
>mixed.every(n => !!n) : boolean
>mixed.every : (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any) => boolean
>mixed.every : { <S extends string | number>(callbackfn: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; }
>mixed : [number, string, string]
>every : (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any) => boolean
>every : { <S extends string | number>(callbackfn: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; }
>n => !!n : (n: string | number) => boolean
>n : string | number
>!!n : boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(
a1(...array2); // Error parameter type is (number|string)[]
~~~~~~
!!! error TS2552: Cannot find name 'array2'. Did you mean 'Array'?
!!! related TS2728 /.ts/lib.es5.d.ts:1385:13: 'Array' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:1403:13: 'Array' is declared here.
a5([1, 2, "string", false, true]); // Error, parameter type is [any, any, [[any]]]
~~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type '[[any]]'.
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/destructuringTuple.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ tests/cases/compiler/destructuringTuple.ts(11,60): error TS2769: No overload mat
!!! error TS2769: Type 'never[]' is not assignable to type '[]'.
!!! error TS2769: Types of property 'length' are incompatible.
!!! error TS2769: Type 'number' is not assignable to type '0'.
!!! related TS6502 /.ts/lib.es5.d.ts:1350:24: The expected type comes from the return type of this signature.
!!! related TS6502 /.ts/lib.es5.d.ts:1356:27: The expected type comes from the return type of this signature.
!!! related TS6502 /.ts/lib.es5.d.ts:1368:24: The expected type comes from the return type of this signature.
!!! related TS6502 /.ts/lib.es5.d.ts:1374:27: The expected type comes from the return type of this signature.
~~
!!! error TS2769: No overload matches this call.
!!! error TS2769: Overload 1 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error.
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/duplicateLocalVariable1.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ export class TestRunner {
>arg2 : Symbol(arg2, Decl(duplicateLocalVariable1.ts, 15, 36))

return (arg1.every(function (val, index) { return val === arg2[index] }));
>arg1.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>arg1.every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>arg1 : Symbol(arg1, Decl(duplicateLocalVariable1.ts, 15, 24))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --))
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>val : Symbol(val, Decl(duplicateLocalVariable1.ts, 16, 37))
>index : Symbol(index, Decl(duplicateLocalVariable1.ts, 16, 41))
>val : Symbol(val, Decl(duplicateLocalVariable1.ts, 16, 37))
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/duplicateLocalVariable1.types
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export class TestRunner {
return (arg1.every(function (val, index) { return val === arg2[index] }));
>(arg1.every(function (val, index) { return val === arg2[index] })) : boolean
>arg1.every(function (val, index) { return val === arg2[index] }) : boolean
>arg1.every : (callbackfn: (value: any, index: number, array: any[]) => unknown, thisArg?: any) => boolean
>arg1.every : { <S extends any>(callbackfn: (value: any, index: number, array: any[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: any, index: number, array: any[]) => unknown, thisArg?: any): boolean; }
>arg1 : any[]
>every : (callbackfn: (value: any, index: number, array: any[]) => unknown, thisArg?: any) => boolean
>every : { <S extends any>(callbackfn: (value: any, index: number, array: any[]) => value is S, thisArg?: any): this is S[]; (callbackfn: (value: any, index: number, array: any[]) => unknown, thisArg?: any): boolean; }
>function (val, index) { return val === arg2[index] } : (val: any, index: number) => boolean
>val : any
>index : number
Expand Down
Loading