UNPKG

fvtt-types

Version:
200 lines (177 loc) 8.02 kB
// This class exists make it as sound as possible to override these parts of the class and make them import type { AnyArray, GetKey, Identity } from "#utils"; // completely unrelated. It's done this way specifically to avoid situations with broken inheritance. declare class Map<K, V> extends globalThis.Map<K, V> { [Symbol.iterator](): any; forEach(...args: AnyArray): any; get(...args: AnyArray): any; } /** * A reusable storage concept which blends the functionality of an Array with the efficient key-based lookup of a Map. * This concept is reused throughout Foundry VTT where a collection of uniquely identified elements is required. * @template T - The type of the objects contained in the Collection */ declare class Collection<V, Methods extends Collection.Methods.Any = Collection.Methods<V>> extends Map<string, V> { constructor(entries?: Iterable<readonly [string, V]> | null); /** * When iterating over a Collection, we should iterate over its values instead of over its entries */ [Symbol.iterator](): MapIterator<V>; /** * Return an Array of all the entry values in the Collection */ get contents(): V[]; /** * Find an entry in the Map using an functional condition. * @see {@link Array.find | `Array#find`} * * @param condition - The functional condition to test. Positional arguments are the value, the index of * iteration, and the collection being searched. * @returns The value, if found, otherwise undefined * * @example Create a new Collection and reference its contents * ```typescript * let c = new Collection([["a", "A"], ["b", "B"], ["c", "C"]]); * c.get("a") === c.find(entry => entry === "A"); // true * ``` */ find<S extends V>( /** @immediate */ condition: (e: V, index: number, collection: Collection<V>) => e is S, ): S | undefined; find(/** @immediate */ condition: (e: V, index: number, collection: Collection<V>) => boolean): V | undefined; /** * Filter the Collection, returning an Array of entries which match a functional condition. * @see {@link Array.filter | `Array#filter`} * * @param condition - The functional condition to test. Positional arguments are the value, the * index of iteration, and the collection being filtered. * @returns An Array of matched values * * @example Filter the Collection for specific entries * ```typescript * let c = new Collection([["a", "AA"], ["b", "AB"], ["c", "CC"]]); * let hasA = c.filters(entry => entry.slice(0) === "A"); * ``` */ filter<S extends V>(/** @immediate */ condition: (e: V, index: number, collection: Collection<V>) => e is S): S[]; filter(/** @immediate */ condition: (e: V, index: number, collection: Collection<V>) => boolean): V[]; /** * Apply a function to each element of the collection * @see {@link Array.forEach | `Array#forEach`} * @param fn - The function to apply to each element * * @example Apply a function to each value in the collection * ```typescript * let c = new Collection([["a", {active: false}], ["b", {active: false}], ["c", {active: false}]]); * c.forEach(e => e.active = true); * ``` */ forEach(/** @immediate */ fn: (e: V) => void): void; /** * Get an element from the Collection by its key. * @param key - The key of the entry to retrieve * @param strict - Throw an Error if the requested key does not exist, * otherwise return undefined. (default: `false`) * @returns The retrieved entry value, if the key exists, otherwise undefined * * @example Get an element from the Collection by key * ```typescript * let c = new Collection([["a", "A"], ["b", "B"], ["c", "C"]]); * c.get("a"); // "A" * c.get("d"); // null * c.get("d", {strict: true}); // throws Error * ``` */ get: Methods["get"]; /** * Get an entry from the Collection by name. * Use of this method assumes that the objects stored in the collection have a "name" attribute. * @param name - The name of the entry to retrieve * @param strict - Throw an Error if the requested name does not exist, * otherwise return undefined. (default: `false`) * @returns The retrieved Entity, if one was found, otherwise undefined * * @example Get an element from the Collection by name (if applicable) * ```typescript * let c = new Collection([["a", "Alfred"], ["b", "Bob"], ["c", "Cynthia"]]); * c.getName("Alfred"); // "Alfred" * c.getName("D"); // undefined * c.getName("D", {strict: true}); // throws Error * ``` */ getName(name: string, { strict }: { strict: true }): V; getName(name: string, { strict }?: { strict?: false }): V | undefined; /** * Transform each element of the Collection into a new form, returning an Array of transformed values * @param transformer - A transformation function applied to each entry value. Positional arguments are the value, the * index of iteration, and the collection being mapped. * @template M - The type of the mapped values * @returns An Array of transformed values */ map<M>(/** @immediate */ transformer: (entity: V, index: number, collection: Collection<V>) => M): M[]; /** * Reduce the Collection by applying an evaluator function and accumulating entries * @see {@link Array.reduce | `Array#reduce`} * @param reducer - A reducer function applied to each entry value. Positional arguments are the accumulator, the * value, the index of iteration, and the collection being reduced. * @param initial - An initial value which accumulates with each iteration * @template A - The type of the accumulator and the return value * @returns The accumulated result * * @example Reduce a collection to an array of transformed values * ```typescript * let c = new Collection([["a", "A"], ["b", "B"], ["c", "C"]]); * let letters = c.reduce((s, l) => { * return s + l; * }, ""); // "ABC" * ``` */ reduce<A>( /** @immediate */ evaluator: (accumulator: A, entity: V, index: number, collection: Collection<V>) => A, initial: A, ): A; /** * Test whether a condition is met by some entry in the Collection. * @see {@link Array.some | `Array#some`} * @param condition - The functional condition to test. Positional arguments are the value, the index of iteration, * and the collection being tested. * @returns Was the test condition passed by at least one entry? */ some(/** @immediate */ condition: (e: V, index: number, collection: Collection<V>) => boolean): boolean; /** * Convert the Collection to a primitive array of its contents. * @returns An array of contained values */ toJSON(): Array<V extends { toJSON: (...args: infer _1) => infer U } ? U : V>; } declare namespace Collection { interface Any extends AnyCollection {} interface AnyConstructor extends Identity<typeof AnyCollection> {} interface GetOptions { /** * Throw an Error if the requested Embedded Document does not exist. * @defaultValue `false` */ strict?: boolean | undefined; } interface Methods<V> { get<Options extends foundry.documents.abstract.DocumentCollection.GetOptions | undefined = undefined>( key: string, { strict }?: Options, ): Collection.GetReturnType<V, Options>; } namespace Methods { interface Any { get(key: string, options?: never): unknown; } } type GetReturnType<T, Options extends GetOptions | undefined> = _ApplyStrict<T, GetKey<Options, "strict", undefined>>; /** @internal */ type _ApplyStrict<ConcreteDocument, Strict extends boolean | undefined> = | (Strict extends false | undefined ? undefined : never) | ConcreteDocument; } declare abstract class AnyCollection extends Collection<unknown, Collection.Methods.Any> { constructor(...args: never); } export default Collection;