Skip to content

Commit

Permalink
add types for set methods proposal (#57230)
Browse files Browse the repository at this point in the history
  • Loading branch information
bakkot committed May 16, 2024
1 parent 4da470d commit e8274f7
Show file tree
Hide file tree
Showing 12 changed files with 1,083 additions and 12 deletions.
77 changes: 77 additions & 0 deletions src/lib/esnext.collection.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,80 @@ interface MapConstructor {
keySelector: (item: T, index: number) => K,
): Map<K, T[]>;
}

interface ReadonlySetLike<T> {
/**
* Despite its name, returns an iterator of the values in the set-like.
*/
keys(): Iterator<T>;
/**
* @returns a boolean indicating whether an element with the specified value exists in the set-like or not.
*/
has(value: T): boolean;
/**
* @returns the number of (unique) elements in the set-like.
*/
readonly size: number;
}

interface Set<T> {
/**
* @returns a new Set containing all the elements in this Set and also all the elements in the argument.
*/
union<U>(other: ReadonlySetLike<U>): Set<T | U>;
/**
* @returns a new Set containing all the elements which are both in this Set and in the argument.
*/
intersection<U>(other: ReadonlySetLike<U>): Set<T & U>;
/**
* @returns a new Set containing all the elements in this Set which are not also in the argument.
*/
difference<U>(other: ReadonlySetLike<U>): Set<T>;
/**
* @returns a new Set containing all the elements which are in either this Set or in the argument, but not in both.
*/
symmetricDifference<U>(other: ReadonlySetLike<U>): Set<T | U>;
/**
* @returns a boolean indicating whether all the elements in this Set are also in the argument.
*/
isSubsetOf(other: ReadonlySetLike<unknown>): boolean;
/**
* @returns a boolean indicating whether all the elements in the argument are also in this Set.
*/
isSupersetOf(other: ReadonlySetLike<unknown>): boolean;
/**
* @returns a boolean indicating whether this Set has no elements in common with the argument.
*/
isDisjointFrom(other: ReadonlySetLike<unknown>): boolean;
}

interface ReadonlySet<T> {
/**
* @returns a new Set containing all the elements in this Set and also all the elements in the argument.
*/
union<U>(other: ReadonlySetLike<U>): Set<T | U>;
/**
* @returns a new Set containing all the elements which are both in this Set and in the argument.
*/
intersection<U>(other: ReadonlySetLike<U>): Set<T & U>;
/**
* @returns a new Set containing all the elements in this Set which are not also in the argument.
*/
difference<U>(other: ReadonlySetLike<U>): Set<T>;
/**
* @returns a new Set containing all the elements which are in either this Set or in the argument, but not in both.
*/
symmetricDifference<U>(other: ReadonlySetLike<U>): Set<T | U>;
/**
* @returns a boolean indicating whether all the elements in this Set are also in the argument.
*/
isSubsetOf(other: ReadonlySetLike<unknown>): boolean;
/**
* @returns a boolean indicating whether all the elements in the argument are also in this Set.
*/
isSupersetOf(other: ReadonlySetLike<unknown>): boolean;
/**
* @returns a boolean indicating whether this Set has no elements in common with the argument.
*/
isDisjointFrom(other: ReadonlySetLike<unknown>): boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export abstract class BaseObservable<T, TChange = void> extends ConvenientObserv

protected readonly observers = new Set<IObserver>();
>observers : Symbol(BaseObservable.observers, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 18, 98))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
>IObserver : Symbol(IObserver, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 0, 0))
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const IterableWeakMap_cleanup = ({ ref, set }: {

readonly set: Set<WeakRef<object>>;
>set : Symbol(set, Decl(esNextWeakRefs_IterableWeakMap.ts, 2, 34))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
>WeakRef : Symbol(WeakRef, Decl(lib.es2021.weakref.d.ts, --, --), Decl(lib.es2021.weakref.d.ts, --, --))

}) => {
Expand Down Expand Up @@ -52,7 +52,7 @@ export class IterableWeakMap<K extends object, V> implements WeakMap<K, V> {

#refSet = new Set<WeakRef<K>>();
>#refSet : Symbol(IterableWeakMap.#refSet, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 72))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
>WeakRef : Symbol(WeakRef, Decl(lib.es2021.weakref.d.ts, --, --), Decl(lib.es2021.weakref.d.ts, --, --))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))

Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/extendsTag1.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
*/
class My extends Set {}
>My : Symbol(My, Decl(bug25101.js, 0, 0))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))

4 changes: 2 additions & 2 deletions tests/baselines/reference/mapGroupBy.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ type Employee = { name: string, role: 'ic' | 'manager' }

const employees: Set<Employee> = new Set();
>employees : Symbol(employees, Decl(mapGroupBy.ts, 5, 5))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
>Employee : Symbol(Employee, Decl(mapGroupBy.ts, 2, 46))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))

const byRole = Map.groupBy(employees, x => x.role);
>byRole : Symbol(byRole, Decl(mapGroupBy.ts, 6, 5))
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/objectGroupBy.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ type Employee = { name: string, role: 'ic' | 'manager' }

const employees: Set<Employee> = new Set();
>employees : Symbol(employees, Decl(objectGroupBy.ts, 5, 5))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
>Employee : Symbol(Employee, Decl(objectGroupBy.ts, 2, 49))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))

const byRole = Object.groupBy(employees, x => x.role);
>byRole : Symbol(byRole, Decl(objectGroupBy.ts, 6, 5))
Expand Down
80 changes: 80 additions & 0 deletions tests/baselines/reference/setMethods.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
setMethods.ts(13,17): error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
Type 'undefined[]' is missing the following properties from type 'ReadonlySetLike<unknown>': has, size
setMethods.ts(19,24): error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
setMethods.ts(25,22): error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
setMethods.ts(31,31): error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
setMethods.ts(37,22): error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
setMethods.ts(43,24): error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
setMethods.ts(49,26): error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.


==== setMethods.ts (7 errors) ====
let numberSet = new Set([0, 1, 2]);

let stringSet = new Set(["a", "b"]);

let numberMap = new Map([[4, {}], [5, {}]]);

let numberSetLike = {
size: 1,
*keys() { yield 3 },
has(x) { return x === 3 },
};

numberSet.union([]);
~~
!!! error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
!!! error TS2345: Type 'undefined[]' is missing the following properties from type 'ReadonlySetLike<unknown>': has, size
numberSet.union(new Set);
numberSet.union(stringSet);
numberSet.union(numberMap);
numberSet.union(numberSetLike);

numberSet.intersection([]);
~~
!!! error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
numberSet.intersection(new Set);
numberSet.intersection(stringSet);
numberSet.intersection(numberMap);
numberSet.intersection(numberSetLike);

numberSet.difference([]);
~~
!!! error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
numberSet.difference(new Set);
numberSet.difference(stringSet);
numberSet.difference(numberMap);
numberSet.difference(numberSetLike);

numberSet.symmetricDifference([]);
~~
!!! error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
numberSet.symmetricDifference(new Set);
numberSet.symmetricDifference(stringSet);
numberSet.symmetricDifference(numberMap);
numberSet.symmetricDifference(numberSetLike);

numberSet.isSubsetOf([]);
~~
!!! error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
numberSet.isSubsetOf(new Set);
numberSet.isSubsetOf(stringSet);
numberSet.isSubsetOf(numberMap);
numberSet.isSubsetOf(numberSetLike);

numberSet.isSupersetOf([]);
~~
!!! error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
numberSet.isSupersetOf(new Set);
numberSet.isSupersetOf(stringSet);
numberSet.isSupersetOf(numberMap);
numberSet.isSupersetOf(numberSetLike);

numberSet.isDisjointFrom([]);
~~
!!! error TS2345: Argument of type 'undefined[]' is not assignable to parameter of type 'ReadonlySetLike<unknown>'.
numberSet.isDisjointFrom(new Set);
numberSet.isDisjointFrom(stringSet);
numberSet.isDisjointFrom(numberMap);
numberSet.isDisjointFrom(numberSetLike);

102 changes: 102 additions & 0 deletions tests/baselines/reference/setMethods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//// [tests/cases/compiler/setMethods.ts] ////

//// [setMethods.ts]
let numberSet = new Set([0, 1, 2]);

let stringSet = new Set(["a", "b"]);

let numberMap = new Map([[4, {}], [5, {}]]);

let numberSetLike = {
size: 1,
*keys() { yield 3 },
has(x) { return x === 3 },
};

numberSet.union([]);
numberSet.union(new Set);
numberSet.union(stringSet);
numberSet.union(numberMap);
numberSet.union(numberSetLike);

numberSet.intersection([]);
numberSet.intersection(new Set);
numberSet.intersection(stringSet);
numberSet.intersection(numberMap);
numberSet.intersection(numberSetLike);

numberSet.difference([]);
numberSet.difference(new Set);
numberSet.difference(stringSet);
numberSet.difference(numberMap);
numberSet.difference(numberSetLike);

numberSet.symmetricDifference([]);
numberSet.symmetricDifference(new Set);
numberSet.symmetricDifference(stringSet);
numberSet.symmetricDifference(numberMap);
numberSet.symmetricDifference(numberSetLike);

numberSet.isSubsetOf([]);
numberSet.isSubsetOf(new Set);
numberSet.isSubsetOf(stringSet);
numberSet.isSubsetOf(numberMap);
numberSet.isSubsetOf(numberSetLike);

numberSet.isSupersetOf([]);
numberSet.isSupersetOf(new Set);
numberSet.isSupersetOf(stringSet);
numberSet.isSupersetOf(numberMap);
numberSet.isSupersetOf(numberSetLike);

numberSet.isDisjointFrom([]);
numberSet.isDisjointFrom(new Set);
numberSet.isDisjointFrom(stringSet);
numberSet.isDisjointFrom(numberMap);
numberSet.isDisjointFrom(numberSetLike);


//// [setMethods.js]
let numberSet = new Set([0, 1, 2]);
let stringSet = new Set(["a", "b"]);
let numberMap = new Map([[4, {}], [5, {}]]);
let numberSetLike = {
size: 1,
*keys() { yield 3; },
has(x) { return x === 3; },
};
numberSet.union([]);
numberSet.union(new Set);
numberSet.union(stringSet);
numberSet.union(numberMap);
numberSet.union(numberSetLike);
numberSet.intersection([]);
numberSet.intersection(new Set);
numberSet.intersection(stringSet);
numberSet.intersection(numberMap);
numberSet.intersection(numberSetLike);
numberSet.difference([]);
numberSet.difference(new Set);
numberSet.difference(stringSet);
numberSet.difference(numberMap);
numberSet.difference(numberSetLike);
numberSet.symmetricDifference([]);
numberSet.symmetricDifference(new Set);
numberSet.symmetricDifference(stringSet);
numberSet.symmetricDifference(numberMap);
numberSet.symmetricDifference(numberSetLike);
numberSet.isSubsetOf([]);
numberSet.isSubsetOf(new Set);
numberSet.isSubsetOf(stringSet);
numberSet.isSubsetOf(numberMap);
numberSet.isSubsetOf(numberSetLike);
numberSet.isSupersetOf([]);
numberSet.isSupersetOf(new Set);
numberSet.isSupersetOf(stringSet);
numberSet.isSupersetOf(numberMap);
numberSet.isSupersetOf(numberSetLike);
numberSet.isDisjointFrom([]);
numberSet.isDisjointFrom(new Set);
numberSet.isDisjointFrom(stringSet);
numberSet.isDisjointFrom(numberMap);
numberSet.isDisjointFrom(numberSetLike);

0 comments on commit e8274f7

Please sign in to comment.