Skip to content

Array.prototype.sort - remove the need for compareFn to handle undefined values #44216

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

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 1 addition & 1 deletion src/lib/es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,7 @@ interface Array<T> {
* [11,2,22,1].sort((a, b) => a - b)
* ```
*/
sort(compareFn?: (a: T, b: T) => number): this;
sort(compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number): this;
/**
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
* @param start The zero-based location in the array from which to start removing elements.
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/implementArrayInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ declare class MyArray<T> implements Array<T> {
reverse(): T[];
shift(): T;
slice(start?: number, end?: number): T[];
sort(compareFn?: (a: T, b: T) => number): this;
sort(compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number): this;
splice(start: number): T[];
splice(start: number, deleteCount: number, ...items: T[]): T[];
unshift(...items: T[]): number;
Expand Down
10 changes: 6 additions & 4 deletions tests/baselines/reference/implementArrayInterface.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,23 @@ declare class MyArray<T> implements Array<T> {
>end : Symbol(end, Decl(implementArrayInterface.ts, 10, 25))
>T : Symbol(T, Decl(implementArrayInterface.ts, 0, 22))

sort(compareFn?: (a: T, b: T) => number): this;
sort(compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number): this;
>sort : Symbol(MyArray.sort, Decl(implementArrayInterface.ts, 10, 45))
>compareFn : Symbol(compareFn, Decl(implementArrayInterface.ts, 11, 9))
>a : Symbol(a, Decl(implementArrayInterface.ts, 11, 22))
>T : Symbol(T, Decl(implementArrayInterface.ts, 0, 22))
>b : Symbol(b, Decl(implementArrayInterface.ts, 11, 27))
>T : Symbol(T, Decl(implementArrayInterface.ts, 0, 22))
>b : Symbol(b, Decl(implementArrayInterface.ts, 11, 57))
>T : Symbol(T, Decl(implementArrayInterface.ts, 0, 22))
>T : Symbol(T, Decl(implementArrayInterface.ts, 0, 22))

splice(start: number): T[];
>splice : Symbol(MyArray.splice, Decl(implementArrayInterface.ts, 11, 51), Decl(implementArrayInterface.ts, 12, 31))
>splice : Symbol(MyArray.splice, Decl(implementArrayInterface.ts, 11, 111), Decl(implementArrayInterface.ts, 12, 31))
>start : Symbol(start, Decl(implementArrayInterface.ts, 12, 11))
>T : Symbol(T, Decl(implementArrayInterface.ts, 0, 22))

splice(start: number, deleteCount: number, ...items: T[]): T[];
>splice : Symbol(MyArray.splice, Decl(implementArrayInterface.ts, 11, 51), Decl(implementArrayInterface.ts, 12, 31))
>splice : Symbol(MyArray.splice, Decl(implementArrayInterface.ts, 11, 111), Decl(implementArrayInterface.ts, 12, 31))
>start : Symbol(start, Decl(implementArrayInterface.ts, 13, 11))
>deleteCount : Symbol(deleteCount, Decl(implementArrayInterface.ts, 13, 25))
>items : Symbol(items, Decl(implementArrayInterface.ts, 13, 46))
Expand Down
10 changes: 5 additions & 5 deletions tests/baselines/reference/implementArrayInterface.types
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ declare class MyArray<T> implements Array<T> {
>start : number
>end : number

sort(compareFn?: (a: T, b: T) => number): this;
>sort : (compareFn?: (a: T, b: T) => number) => this
>compareFn : (a: T, b: T) => number
>a : T
>b : T
sort(compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number): this;
>sort : (compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number) => this
>compareFn : (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number
>a : T extends undefined ? never : T
>b : T extends undefined ? never : T

splice(start: number): T[];
>splice : { (start: number): T[]; (start: number, deleteCount: number, ...items: T[]): T[]; }
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/restInvalidArgumentType.types
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function f<T extends { b: string }>(p1: T, p2: T[]) {
>p1 : T

var {...r2} = p2; // OK
>r2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray<T>[]): T[]; concat(...items: (T | ConcatArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
>r2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray<T>[]): T[]; concat(...items: (T | ConcatArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
>p2 : T[]

var {...r3} = t; // Error, generic type paramter
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/spreadInvalidArgumentType.types
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ function f<T extends { b: string }>(p1: T, p2: T[]) {
>p1 : T

var o2 = { ...p2 }; // OK
>o2 : { [x: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray<T>[]): T[]; concat(...items: (T | ConcatArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
>{ ...p2 } : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray<T>[]): T[]; concat(...items: (T | ConcatArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
>o2 : { [x: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray<T>[]): T[]; concat(...items: (T | ConcatArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
>{ ...p2 } : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray<T>[]): T[]; concat(...items: (T | ConcatArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
>p2 : T[]

var o3 = { ...t }; // OK, generic type paramter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -565,17 +565,17 @@ class ListWrapper {

l.sort(compareFn);
>l.sort(compareFn) : T[]
>l.sort : (compareFn?: (a: T, b: T) => number) => T[]
>l.sort : (compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number) => T[]
>l : T[]
>sort : (compareFn?: (a: T, b: T) => number) => T[]
>sort : (compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number) => T[]
>compareFn : (a: T, b: T) => number

} else {
l.sort();
>l.sort() : T[]
>l.sort : (compareFn?: (a: T, b: T) => number) => T[]
>l.sort : (compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number) => T[]
>l : T[]
>sort : (compareFn?: (a: T, b: T) => number) => T[]
>sort : (compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number) => T[]
}
}
static toString<T>(dit: typeof ListWrapper, l: T[]): string { return l.toString(); }
Expand Down
2 changes: 1 addition & 1 deletion tests/cases/compiler/implementArrayInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ declare class MyArray<T> implements Array<T> {
reverse(): T[];
shift(): T;
slice(start?: number, end?: number): T[];
sort(compareFn?: (a: T, b: T) => number): this;
sort(compareFn?: (a: T extends undefined ? never : T, b: T extends undefined ? never : T) => number): this;
splice(start: number): T[];
splice(start: number, deleteCount: number, ...items: T[]): T[];
unshift(...items: T[]): number;
Expand Down