mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-17 12:03:31 +01:00
feat(collection): honour subclassing via @@species in static methods (#10723)
* feat(collection): use @@species in static methods * test(collection): subclassing tests * chore: trigger ci --------- Co-authored-by: almeidx <github@almeidx.dev>
This commit is contained in:
@@ -1099,3 +1099,58 @@ describe('findLastKey() tests', () => {
|
|||||||
}, null);
|
}, null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('subclassing tests', () => {
|
||||||
|
class DerivedCollection<Key, Value> extends Collection<Key, Value> {}
|
||||||
|
|
||||||
|
test('constructor[Symbol.species]', () => {
|
||||||
|
expect(DerivedCollection[Symbol.species]).toStrictEqual(DerivedCollection);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('methods that construct new collections return subclassed objects', () => {
|
||||||
|
const coll = new DerivedCollection();
|
||||||
|
|
||||||
|
test('filter()', () => {
|
||||||
|
expect(coll.filter(Boolean)).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('partition()', () => {
|
||||||
|
for (const partition of coll.partition(Boolean)) {
|
||||||
|
expect(partition).toBeInstanceOf(DerivedCollection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
test('flatMap()', () => {
|
||||||
|
expect(coll.flatMap(() => new Collection())).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('mapValues()', () => {
|
||||||
|
expect(coll.mapValues(Object)).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('clone()', () => {
|
||||||
|
expect(coll.clone()).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('intersection()', () => {
|
||||||
|
expect(coll.intersection(new Collection())).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('union()', () => {
|
||||||
|
expect(coll.union(new Collection())).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('difference()', () => {
|
||||||
|
expect(coll.difference(new Collection())).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('symmetricDifference()', () => {
|
||||||
|
expect(coll.symmetricDifference(new Collection())).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('merge()', () => {
|
||||||
|
const fn = () => ({ keep: false }) as const; // eslint-disable-line unicorn/consistent-function-scoping
|
||||||
|
expect(coll.merge(new Collection(), fn, fn, fn)).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('toReversed()', () => {
|
||||||
|
expect(coll.toReversed()).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('toSorted()', () => {
|
||||||
|
expect(coll.toSorted()).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
test('Collection.combineEntries()', () => {
|
||||||
|
expect(DerivedCollection.combineEntries([], Object)).toBeInstanceOf(DerivedCollection);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ export type ReadonlyCollection<Key, Value> = Omit<
|
|||||||
|
|
||||||
export interface Collection<Key, Value> {
|
export interface Collection<Key, Value> {
|
||||||
/**
|
/**
|
||||||
* Ambient declaration to allow `this.constructor[@@species]` in class methods.
|
* Ambient declaration to allow references to `this.constructor` in class methods.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
constructor: typeof Collection & { readonly [Symbol.species]: typeof Collection };
|
constructor: typeof Collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1076,7 +1076,7 @@ export class Collection<Key, Value> extends Map<Key, Value> {
|
|||||||
entries: Iterable<[Key, Value]>,
|
entries: Iterable<[Key, Value]>,
|
||||||
combine: (firstValue: Value, secondValue: Value, key: Key) => Value,
|
combine: (firstValue: Value, secondValue: Value, key: Key) => Value,
|
||||||
): Collection<Key, Value> {
|
): Collection<Key, Value> {
|
||||||
const coll = new Collection<Key, Value>();
|
const coll = new this[Symbol.species]<Key, Value>();
|
||||||
for (const [key, value] of entries) {
|
for (const [key, value] of entries) {
|
||||||
if (coll.has(key)) {
|
if (coll.has(key)) {
|
||||||
coll.set(key, combine(coll.get(key)!, value, key));
|
coll.set(key, combine(coll.get(key)!, value, key));
|
||||||
@@ -1087,6 +1087,11 @@ export class Collection<Key, Value> extends Map<Key, Value> {
|
|||||||
|
|
||||||
return coll;
|
return coll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
declare public static readonly [Symbol.species]: typeof Collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user