diff --git a/apps/website/src/components/ItemLink.tsx b/apps/website/src/components/ItemLink.tsx index 7a21ae8037dd..13126bf51a19 100644 --- a/apps/website/src/components/ItemLink.tsx +++ b/apps/website/src/components/ItemLink.tsx @@ -6,7 +6,7 @@ import { usePathname } from 'next/navigation'; import type { PropsWithChildren } from 'react'; import { useCurrentPathMeta } from '~/hooks/useCurrentPathMeta'; -export interface ItemLinkProps extends Omit, 'href'> { +export interface ItemLinkProps extends Omit, 'href'> { readonly className?: string; /** * The URI of the api item to link to. (e.g. `/RestManager`) @@ -29,7 +29,7 @@ export interface ItemLinkProps extends Omit, 'hre * This component only needs the relative path to the item, and will automatically * generate the full path to the item client-side. */ -export function ItemLink(props: PropsWithChildren>) { +export function ItemLink(props: PropsWithChildren>) { const pathname = usePathname(); const { packageName, version } = useCurrentPathMeta(); diff --git a/apps/website/src/util/members.ts b/apps/website/src/util/members.ts index 020c7363fca1..d12c1b0cdfeb 100644 --- a/apps/website/src/util/members.ts +++ b/apps/website/src/util/members.ts @@ -6,9 +6,9 @@ import type { ApiItem, ApiItemContainerMixin } from '@discordjs/api-extractor-mo * @param parent - The parent to resolve the inherited members of. * @param predicate - A predicate to filter the members by. */ -export function resolveMembers( +export function resolveMembers( parent: ApiItemContainerMixin, - predicate: (item: ApiItem) => item is T, + predicate: (item: ApiItem) => item is WantedItem, ) { const seenItems = new Set(); const inheritedMembers = parent.findMembersWithInheritance().items.reduce((acc, item) => { @@ -25,14 +25,17 @@ export function resolveMembers( } return acc; - }, new Array<{ inherited?: ApiItemContainerMixin | undefined; item: T }>()); + }, new Array<{ inherited?: ApiItemContainerMixin | undefined; item: WantedItem }>()); const mergedMembers = parent .getMergedSiblings() .filter((sibling) => sibling.containerKey !== parent.containerKey) .flatMap((sibling) => (sibling as ApiItemContainerMixin).findMembersWithInheritance().items) .filter((item) => predicate(item) && !seenItems.has(item.containerKey)) - .map((item) => ({ item: item as T, inherited: item.parent ? (item.parent as ApiItemContainerMixin) : undefined })); + .map((item) => ({ + item: item as WantedItem, + inherited: item.parent ? (item.parent as ApiItemContainerMixin) : undefined, + })); return [...inheritedMembers, ...mergedMembers]; } diff --git a/eslint.config.js b/eslint.config.js index 0e5dc30913a4..11eedddc1b53 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -25,6 +25,17 @@ const typeScriptRuleset = merge(...typescript, { }, rules: { '@typescript-eslint/consistent-type-definitions': [2, 'interface'], + '@typescript-eslint/naming-convention': [ + 2, + { + selector: 'typeParameter', + format: ['PascalCase'], + custom: { + regex: '^\\w{3,}', + match: true, + }, + }, + ], }, settings: { 'import/resolver': { @@ -110,6 +121,10 @@ export default [ '@typescript-eslint/no-this-alias': 0, }, }, + { + files: [`packages/{api-extractor,api-extractor-model,api-extractor-utils}/**/*${commonFiles}`], + rules: { '@typescript-eslint/naming-convention': 0 }, + }, reactRuleset, nextRuleset, edgeRuleset, diff --git a/packages/brokers/src/brokers/Broker.ts b/packages/brokers/src/brokers/Broker.ts index 7664051cd767..4e298725ea5c 100644 --- a/packages/brokers/src/brokers/Broker.ts +++ b/packages/brokers/src/brokers/Broker.ts @@ -75,7 +75,7 @@ export interface IPubSubBroker> /** * Publishes an event */ - publish(event: T, data: TEvents[T]): Promise; + publish(event: Event, data: TEvents[Event]): Promise; } export interface IRPCBroker, TResponses extends Record> @@ -84,5 +84,9 @@ export interface IRPCBroker, TResponses exte /** * Makes an RPC call */ - call(event: T, data: TEvents[T], timeoutDuration?: number): Promise; + call( + event: Event, + data: TEvents[Event], + timeoutDuration?: number, + ): Promise; } diff --git a/packages/brokers/src/brokers/redis/PubSubRedis.ts b/packages/brokers/src/brokers/redis/PubSubRedis.ts index 79b0b41fcbb7..ddba1e97df2d 100644 --- a/packages/brokers/src/brokers/redis/PubSubRedis.ts +++ b/packages/brokers/src/brokers/redis/PubSubRedis.ts @@ -36,7 +36,7 @@ export class PubSubRedisBroker> /** * {@inheritDoc IPubSubBroker.publish} */ - public async publish(event: T, data: TEvents[T]): Promise { + public async publish(event: Event, data: TEvents[Event]): Promise { await this.options.redisClient.xadd( event as string, '*', diff --git a/packages/brokers/src/brokers/redis/RPCRedis.ts b/packages/brokers/src/brokers/redis/RPCRedis.ts index eb06109bb89e..f34608429331 100644 --- a/packages/brokers/src/brokers/redis/RPCRedis.ts +++ b/packages/brokers/src/brokers/redis/RPCRedis.ts @@ -83,11 +83,11 @@ export class RPCRedisBroker, TResponses exte /** * {@inheritDoc IRPCBroker.call} */ - public async call( - event: T, - data: TEvents[T], + public async call( + event: Event, + data: TEvents[Event], timeoutDuration: number = this.options.timeout, - ): Promise { + ): Promise { const id = await this.options.redisClient.xadd( event as string, '*', @@ -103,7 +103,7 @@ export class RPCRedisBroker, TResponses exte const timedOut = new Error(`timed out after ${timeoutDuration}ms`); await this.streamReadClient.subscribe(rpcChannel); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { const timeout = setTimeout(() => reject(timedOut), timeoutDuration).unref(); this.promises.set(id!, { resolve, reject, timeout }); diff --git a/packages/builders/src/components/ActionRow.ts b/packages/builders/src/components/ActionRow.ts index 05ed65684fb5..ade84ac4690c 100644 --- a/packages/builders/src/components/ActionRow.ts +++ b/packages/builders/src/components/ActionRow.ts @@ -54,15 +54,15 @@ export type AnyComponentBuilder = MessageActionRowComponentBuilder | ModalAction /** * A builder that creates API-compatible JSON data for action rows. * - * @typeParam T - The types of components this action row holds + * @typeParam ComponentType - The types of components this action row holds */ -export class ActionRowBuilder extends ComponentBuilder< +export class ActionRowBuilder extends ComponentBuilder< APIActionRowComponent > { /** * The components within this action row. */ - public readonly components: T[]; + public readonly components: ComponentType[]; /** * Creates a new action row from API data. @@ -100,7 +100,7 @@ export class ActionRowBuilder extends ComponentBu */ public constructor({ components, ...data }: Partial> = {}) { super({ type: ComponentType.ActionRow, ...data }); - this.components = (components?.map((component) => createComponentBuilder(component)) ?? []) as T[]; + this.components = (components?.map((component) => createComponentBuilder(component)) ?? []) as ComponentType[]; } /** @@ -108,7 +108,7 @@ export class ActionRowBuilder extends ComponentBu * * @param components - The components to add */ - public addComponents(...components: RestOrArray) { + public addComponents(...components: RestOrArray) { this.components.push(...normalizeArray(components)); return this; } @@ -118,7 +118,7 @@ export class ActionRowBuilder extends ComponentBu * * @param components - The components to set */ - public setComponents(...components: RestOrArray) { + public setComponents(...components: RestOrArray) { this.components.splice(0, this.components.length, ...normalizeArray(components)); return this; } @@ -126,10 +126,10 @@ export class ActionRowBuilder extends ComponentBu /** * {@inheritDoc ComponentBuilder.toJSON} */ - public toJSON(): APIActionRowComponent> { + public toJSON(): APIActionRowComponent> { return { ...this.data, components: this.components.map((component) => component.toJSON()), - } as APIActionRowComponent>; + } as APIActionRowComponent>; } } diff --git a/packages/builders/src/components/Components.ts b/packages/builders/src/components/Components.ts index eb75e38d0f32..74efe8782dc0 100644 --- a/packages/builders/src/components/Components.ts +++ b/packages/builders/src/components/Components.ts @@ -55,21 +55,23 @@ export interface MappedComponentTypes { /** * Factory for creating components from API data. * - * @typeParam T - The type of component to use + * @typeParam ComponentType - The type of component to use * @param data - The API data to transform to a component class */ -export function createComponentBuilder( +export function createComponentBuilder( // eslint-disable-next-line @typescript-eslint/sort-type-constituents - data: (APIModalComponent | APIMessageComponent) & { type: T }, -): MappedComponentTypes[T]; + data: (APIModalComponent | APIMessageComponent) & { type: ComponentType }, +): MappedComponentTypes[ComponentType]; /** * Factory for creating components from API data. * - * @typeParam C - The type of component to use + * @typeParam ComponentBuilder - The type of component to use * @param data - The API data to transform to a component class */ -export function createComponentBuilder(data: C): C; +export function createComponentBuilder( + data: ComponentBuilder, +): ComponentBuilder; export function createComponentBuilder( data: APIMessageComponent | APIModalComponent | MessageComponentBuilder, diff --git a/packages/builders/src/interactions/slashCommands/Assertions.ts b/packages/builders/src/interactions/slashCommands/Assertions.ts index d61da838fa82..f98e5be3ad5c 100644 --- a/packages/builders/src/interactions/slashCommands/Assertions.ts +++ b/packages/builders/src/interactions/slashCommands/Assertions.ts @@ -66,8 +66,8 @@ export function validateChoicesLength(amountAdding: number, choices?: APIApplica } export function assertReturnOfBuilder< - T extends ApplicationCommandOptionBase | SlashCommandSubcommandBuilder | SlashCommandSubcommandGroupBuilder, ->(input: unknown, ExpectedInstanceOf: new () => T): asserts input is T { + ReturnType extends ApplicationCommandOptionBase | SlashCommandSubcommandBuilder | SlashCommandSubcommandGroupBuilder, +>(input: unknown, ExpectedInstanceOf: new () => ReturnType): asserts input is ReturnType { s.instance(ExpectedInstanceOf).parse(input); } diff --git a/packages/builders/src/interactions/slashCommands/mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin.ts b/packages/builders/src/interactions/slashCommands/mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin.ts index 29fdd1e3cabf..79ee77d4e23d 100644 --- a/packages/builders/src/interactions/slashCommands/mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin.ts +++ b/packages/builders/src/interactions/slashCommands/mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin.ts @@ -14,11 +14,11 @@ const booleanPredicate = s.boolean; /** * This mixin holds choices and autocomplete symbols used for options. */ -export class ApplicationCommandOptionWithChoicesAndAutocompleteMixin { +export class ApplicationCommandOptionWithChoicesAndAutocompleteMixin { /** * The choices of this option. */ - public readonly choices?: APIApplicationCommandOptionChoice[]; + public readonly choices?: APIApplicationCommandOptionChoice[]; /** * Whether this option utilizes autocomplete. @@ -37,7 +37,7 @@ export class ApplicationCommandOptionWithChoicesAndAutocompleteMixin[]): this { + public addChoices(...choices: APIApplicationCommandOptionChoice[]): this { if (choices.length > 0 && this.autocomplete) { throw new RangeError('Autocomplete and choices are mutually exclusive to each other.'); } @@ -69,7 +69,7 @@ export class ApplicationCommandOptionWithChoicesAndAutocompleteMixin[]>(...choices: Input): this { + public setChoices[]>(...choices: Input): this { if (choices.length > 0 && this.autocomplete) { throw new RangeError('Autocomplete and choices are mutually exclusive to each other.'); } diff --git a/packages/builders/src/interactions/slashCommands/mixins/SharedSlashCommandOptions.ts b/packages/builders/src/interactions/slashCommands/mixins/SharedSlashCommandOptions.ts index a3e881931a8b..e44f659a69b1 100644 --- a/packages/builders/src/interactions/slashCommands/mixins/SharedSlashCommandOptions.ts +++ b/packages/builders/src/interactions/slashCommands/mixins/SharedSlashCommandOptions.ts @@ -148,13 +148,15 @@ export class SharedSlashCommandOptions { * @param Instance - The instance of whatever is being added * @internal */ - private _sharedAddOptionMethod( + private _sharedAddOptionMethod( input: - | Omit - | Omit - | T - | ((builder: T) => Omit | Omit | T), - Instance: new () => T, + | Omit + | Omit + | OptionBuilder + | (( + builder: OptionBuilder, + ) => Omit | Omit | OptionBuilder), + Instance: new () => OptionBuilder, ): ShouldOmitSubcommandFunctions extends true ? Omit : this { const { options } = this; diff --git a/packages/builders/src/util/normalizeArray.ts b/packages/builders/src/util/normalizeArray.ts index bf31830a324b..1ff485008f08 100644 --- a/packages/builders/src/util/normalizeArray.ts +++ b/packages/builders/src/util/normalizeArray.ts @@ -1,12 +1,12 @@ /** * Normalizes data that is a rest parameter or an array into an array with a depth of 1. * - * @typeParam T - The data that must satisfy {@link RestOrArray}. + * @typeParam ItemType - The data that must satisfy {@link RestOrArray}. * @param arr - The (possibly variadic) data to normalize */ -export function normalizeArray(arr: RestOrArray): T[] { +export function normalizeArray(arr: RestOrArray): ItemType[] { if (Array.isArray(arr[0])) return arr[0]; - return arr as T[]; + return arr as ItemType[]; } /** @@ -16,4 +16,4 @@ export function normalizeArray(arr: RestOrArray): T[] { * This type is used throughout builders to ensure both an array and variadic arguments * may be used. It is normalized with {@link normalizeArray}. */ -export type RestOrArray = T[] | [T[]]; +export type RestOrArray = Type[] | [Type[]]; diff --git a/packages/collection/__tests__/collection.test.ts b/packages/collection/__tests__/collection.test.ts index f3c80c31dbc6..fd538aca5446 100644 --- a/packages/collection/__tests__/collection.test.ts +++ b/packages/collection/__tests__/collection.test.ts @@ -3,13 +3,13 @@ import { describe, test, expect } from 'vitest'; import { Collection } from '../src/index.js'; -type TestCollection = Collection; +type TestCollection = Collection; -function createCollection(): TestCollection { +function createCollection(): TestCollection { return new Collection(); } -function createCollectionFrom(...entries: [key: string, value: V][]): TestCollection { +function createCollectionFrom(...entries: [key: string, value: Value][]): TestCollection { return new Collection(entries); } diff --git a/packages/collection/src/collection.ts b/packages/collection/src/collection.ts index fcee69f7fa2d..41072060d89a 100644 --- a/packages/collection/src/collection.ts +++ b/packages/collection/src/collection.ts @@ -4,8 +4,8 @@ */ export interface CollectionConstructor { new (): Collection; - new (entries?: readonly (readonly [K, V])[] | null): Collection; - new (iterable: Iterable): Collection; + new (entries?: readonly (readonly [Key, Value])[] | null): Collection; + new (iterable: Iterable): Collection; readonly prototype: Collection; readonly [Symbol.species]: CollectionConstructor; } @@ -13,18 +13,18 @@ export interface CollectionConstructor { /** * Represents an immutable version of a collection */ -export type ReadonlyCollection = Omit< - Collection, +export type ReadonlyCollection = Omit< + Collection, 'delete' | 'ensure' | 'forEach' | 'get' | 'reverse' | 'set' | 'sort' | 'sweep' > & - ReadonlyMap; + ReadonlyMap; /** * Separate interface for the constructor so that emitted js does not have a constructor that overwrites itself * * @internal */ -export interface Collection extends Map { +export interface Collection extends Map { constructor: CollectionConstructor; } @@ -32,10 +32,10 @@ export interface Collection extends Map { * A Map with additional utility methods. This is used throughout discord.js rather than Arrays for anything that has * an ID, for significantly improved performance and ease-of-use. * - * @typeParam K - The key type this collection holds - * @typeParam V - The value type this collection holds + * @typeParam Key - The key type this collection holds + * @typeParam Value - The value type this collection holds */ -export class Collection extends Map { +export class Collection extends Map { /** * Obtains the value of the given key if it exists, otherwise sets and returns the value provided by the default value generator. * @@ -46,7 +46,7 @@ export class Collection extends Map { * collection.ensure(guildId, () => defaultGuildConfig); * ``` */ - public ensure(key: K, defaultValueGenerator: (key: K, collection: this) => V): V { + public ensure(key: Key, defaultValueGenerator: (key: Key, collection: this) => Value): Value { if (this.has(key)) return this.get(key)!; if (typeof defaultValueGenerator !== 'function') throw new TypeError(`${defaultValueGenerator} is not a function`); const defaultValue = defaultValueGenerator(key, this); @@ -60,7 +60,7 @@ export class Collection extends Map { * @param keys - The keys of the elements to check for * @returns `true` if all of the elements exist, `false` if at least one does not exist. */ - public hasAll(...keys: K[]) { + public hasAll(...keys: Key[]) { return keys.every((key) => super.has(key)); } @@ -70,7 +70,7 @@ export class Collection extends Map { * @param keys - The keys of the elements to check for * @returns `true` if any of the elements exist, `false` if none exist. */ - public hasAny(...keys: K[]) { + public hasAny(...keys: Key[]) { return keys.some((key) => super.has(key)); } @@ -80,14 +80,14 @@ export class Collection extends Map { * @param amount - Amount of values to obtain from the beginning * @returns A single value if no amount is provided or an array of values, starting from the end if amount is negative */ - public first(): V | undefined; - public first(amount: number): V[]; - public first(amount?: number): V | V[] | undefined { + public first(): Value | undefined; + public first(amount: number): Value[]; + public first(amount?: number): Value | Value[] | undefined { if (amount === undefined) return this.values().next().value; if (amount < 0) return this.last(amount * -1); amount = Math.min(this.size, amount); const iter = this.values(); - return Array.from({ length: amount }, (): V => iter.next().value); + return Array.from({ length: amount }, (): Value => iter.next().value); } /** @@ -97,14 +97,14 @@ export class Collection extends Map { * @returns A single key if no amount is provided or an array of keys, starting from the end if * amount is negative */ - public firstKey(): K | undefined; - public firstKey(amount: number): K[]; - public firstKey(amount?: number): K | K[] | undefined { + public firstKey(): Key | undefined; + public firstKey(amount: number): Key[]; + public firstKey(amount?: number): Key | Key[] | undefined { if (amount === undefined) return this.keys().next().value; if (amount < 0) return this.lastKey(amount * -1); amount = Math.min(this.size, amount); const iter = this.keys(); - return Array.from({ length: amount }, (): K => iter.next().value); + return Array.from({ length: amount }, (): Key => iter.next().value); } /** @@ -114,9 +114,9 @@ export class Collection extends Map { * @returns A single value if no amount is provided or an array of values, starting from the start if * amount is negative */ - public last(): V | undefined; - public last(amount: number): V[]; - public last(amount?: number): V | V[] | undefined { + public last(): Value | undefined; + public last(amount: number): Value[]; + public last(amount?: number): Value | Value[] | undefined { const arr = [...this.values()]; if (amount === undefined) return arr[arr.length - 1]; if (amount < 0) return this.first(amount * -1); @@ -131,9 +131,9 @@ export class Collection extends Map { * @returns A single key if no amount is provided or an array of keys, starting from the start if * amount is negative */ - public lastKey(): K | undefined; - public lastKey(amount: number): K[]; - public lastKey(amount?: number): K | K[] | undefined { + public lastKey(): Key | undefined; + public lastKey(amount: number): Key[]; + public lastKey(amount?: number): Key | Key[] | undefined { const arr = [...this.keys()]; if (amount === undefined) return arr[arr.length - 1]; if (amount < 0) return this.firstKey(amount * -1); @@ -173,15 +173,15 @@ export class Collection extends Map { * @param amount - Amount of values to obtain randomly * @returns A single value if no amount is provided or an array of values */ - public random(): V | undefined; - public random(amount: number): V[]; - public random(amount?: number): V | V[] | undefined { + public random(): Value | undefined; + public random(amount: number): Value[]; + public random(amount?: number): Value | Value[] | undefined { const arr = [...this.values()]; if (amount === undefined) return arr[Math.floor(Math.random() * arr.length)]; if (!arr.length || !amount) return []; return Array.from( { length: Math.min(amount, arr.length) }, - (): V => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]!, + (): Value => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]!, ); } @@ -191,15 +191,15 @@ export class Collection extends Map { * @param amount - Amount of keys to obtain randomly * @returns A single key if no amount is provided or an array */ - public randomKey(): K | undefined; - public randomKey(amount: number): K[]; - public randomKey(amount?: number): K | K[] | undefined { + public randomKey(): Key | undefined; + public randomKey(amount: number): Key[]; + public randomKey(amount?: number): Key | Key[] | undefined { const arr = [...this.keys()]; if (amount === undefined) return arr[Math.floor(Math.random() * arr.length)]; if (!arr.length || !amount) return []; return Array.from( { length: Math.min(amount, arr.length) }, - (): K => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]!, + (): Key => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]!, ); } @@ -228,14 +228,19 @@ export class Collection extends Map { * collection.find(user => user.username === 'Bob'); * ``` */ - public find(fn: (value: V, key: K, collection: this) => value is V2): V2 | undefined; - public find(fn: (value: V, key: K, collection: this) => unknown): V | undefined; - public find( - fn: (this: This, value: V, key: K, collection: this) => value is V2, + public find( + fn: (value: Value, key: Key, collection: this) => value is NewValue, + ): NewValue | undefined; + public find(fn: (value: Value, key: Key, collection: this) => unknown): Value | undefined; + public find( + fn: (this: This, value: Value, key: Key, collection: this) => value is NewValue, thisArg: This, - ): V2 | undefined; - public find(fn: (this: This, value: V, key: K, collection: this) => unknown, thisArg: This): V | undefined; - public find(fn: (value: V, key: K, collection: this) => unknown, thisArg?: unknown): V | undefined { + ): NewValue | undefined; + public find( + fn: (this: This, value: Value, key: Key, collection: this) => unknown, + thisArg: This, + ): Value | undefined; + public find(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): Value | undefined { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); for (const [key, val] of this) { @@ -257,14 +262,19 @@ export class Collection extends Map { * collection.findKey(user => user.username === 'Bob'); * ``` */ - public findKey(fn: (value: V, key: K, collection: this) => key is K2): K2 | undefined; - public findKey(fn: (value: V, key: K, collection: this) => unknown): K | undefined; - public findKey( - fn: (this: This, value: V, key: K, collection: this) => key is K2, + public findKey( + fn: (value: Value, key: Key, collection: this) => key is NewKey, + ): NewKey | undefined; + public findKey(fn: (value: Value, key: Key, collection: this) => unknown): Key | undefined; + public findKey( + fn: (this: This, value: Value, key: Key, collection: this) => key is NewKey, + thisArg: This, + ): NewKey | undefined; + public findKey( + fn: (this: This, value: Value, key: Key, collection: this) => unknown, thisArg: This, - ): K2 | undefined; - public findKey(fn: (this: This, value: V, key: K, collection: this) => unknown, thisArg: This): K | undefined; - public findKey(fn: (value: V, key: K, collection: this) => unknown, thisArg?: unknown): K | undefined { + ): Key | undefined; + public findKey(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): Key | undefined { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); for (const [key, val] of this) { @@ -281,14 +291,19 @@ export class Collection extends Map { * @param fn - The function to test with (should return a boolean) * @param thisArg - Value to use as `this` when executing the function */ - public findLast(fn: (value: V, key: K, collection: this) => value is V2): V2 | undefined; - public findLast(fn: (value: V, key: K, collection: this) => unknown): V | undefined; - public findLast( - fn: (this: This, value: V, key: K, collection: this) => value is V2, + public findLast( + fn: (value: Value, key: Key, collection: this) => value is NewValue, + ): NewValue | undefined; + public findLast(fn: (value: Value, key: Key, collection: this) => unknown): Value | undefined; + public findLast( + fn: (this: This, value: Value, key: Key, collection: this) => value is NewValue, + thisArg: This, + ): NewValue | undefined; + public findLast( + fn: (this: This, value: Value, key: Key, collection: this) => unknown, thisArg: This, - ): V2 | undefined; - public findLast(fn: (this: This, value: V, key: K, collection: this) => unknown, thisArg: This): V | undefined; - public findLast(fn: (value: V, key: K, collection: this) => unknown, thisArg?: unknown): V | undefined { + ): Value | undefined; + public findLast(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): Value | undefined { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); const entries = [...this.entries()]; @@ -309,17 +324,19 @@ export class Collection extends Map { * @param fn - The function to test with (should return a boolean) * @param thisArg - Value to use as `this` when executing the function */ - public findLastKey(fn: (value: V, key: K, collection: this) => key is K2): K2 | undefined; - public findLastKey(fn: (value: V, key: K, collection: this) => unknown): K | undefined; - public findLastKey( - fn: (this: This, value: V, key: K, collection: this) => key is K2, + public findLastKey( + fn: (value: Value, key: Key, collection: this) => key is NewKey, + ): NewKey | undefined; + public findLastKey(fn: (value: Value, key: Key, collection: this) => unknown): Key | undefined; + public findLastKey( + fn: (this: This, value: Value, key: Key, collection: this) => key is NewKey, thisArg: This, - ): K2 | undefined; + ): NewKey | undefined; public findLastKey( - fn: (this: This, value: V, key: K, collection: this) => unknown, + fn: (this: This, value: Value, key: Key, collection: this) => unknown, thisArg: This, - ): K | undefined; - public findLastKey(fn: (value: V, key: K, collection: this) => unknown, thisArg?: unknown): K | undefined { + ): Key | undefined; + public findLastKey(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): Key | undefined { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); const entries = [...this.entries()]; @@ -339,9 +356,9 @@ export class Collection extends Map { * @param thisArg - Value to use as `this` when executing the function * @returns The number of removed entries */ - public sweep(fn: (value: V, key: K, collection: this) => unknown): number; - public sweep(fn: (this: T, value: V, key: K, collection: this) => unknown, thisArg: T): number; - public sweep(fn: (value: V, key: K, collection: this) => unknown, thisArg?: unknown): number { + public sweep(fn: (value: Value, key: Key, collection: this) => unknown): number; + public sweep(fn: (this: This, value: Value, key: Key, collection: this) => unknown, thisArg: This): number; + public sweep(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): number { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); const previousSize = this.size; @@ -364,22 +381,29 @@ export class Collection extends Map { * collection.filter(user => user.username === 'Bob'); * ``` */ - public filter(fn: (value: V, key: K, collection: this) => key is K2): Collection; - public filter(fn: (value: V, key: K, collection: this) => value is V2): Collection; - public filter(fn: (value: V, key: K, collection: this) => unknown): Collection; - public filter( - fn: (this: This, value: V, key: K, collection: this) => key is K2, + public filter( + fn: (value: Value, key: Key, collection: this) => key is NewKey, + ): Collection; + public filter( + fn: (value: Value, key: Key, collection: this) => value is NewValue, + ): Collection; + public filter(fn: (value: Value, key: Key, collection: this) => unknown): Collection; + public filter( + fn: (this: This, value: Value, key: Key, collection: this) => key is NewKey, thisArg: This, - ): Collection; - public filter( - fn: (this: This, value: V, key: K, collection: this) => value is V2, + ): Collection; + public filter( + fn: (this: This, value: Value, key: Key, collection: this) => value is NewValue, thisArg: This, - ): Collection; - public filter(fn: (this: This, value: V, key: K, collection: this) => unknown, thisArg: This): Collection; - public filter(fn: (value: V, key: K, collection: this) => unknown, thisArg?: unknown): Collection { + ): Collection; + public filter( + fn: (this: This, value: Value, key: Key, collection: this) => unknown, + thisArg: This, + ): Collection; + public filter(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): Collection { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); - const results = new this.constructor[Symbol.species](); + const results = new this.constructor[Symbol.species](); for (const [key, val] of this) { if (fn(val, key, this)) results.set(key, val); } @@ -398,34 +422,36 @@ export class Collection extends Map { * const [big, small] = collection.partition(guild => guild.memberCount > 250); * ``` */ - public partition( - fn: (value: V, key: K, collection: this) => key is K2, - ): [Collection, Collection, V>]; - public partition( - fn: (value: V, key: K, collection: this) => value is V2, - ): [Collection, Collection>]; - public partition(fn: (value: V, key: K, collection: this) => unknown): [Collection, Collection]; - public partition( - fn: (this: This, value: V, key: K, collection: this) => key is K2, + public partition( + fn: (value: Value, key: Key, collection: this) => key is NewKey, + ): [Collection, Collection, Value>]; + public partition( + fn: (value: Value, key: Key, collection: this) => value is NewValue, + ): [Collection, Collection>]; + public partition( + fn: (value: Value, key: Key, collection: this) => unknown, + ): [Collection, Collection]; + public partition( + fn: (this: This, value: Value, key: Key, collection: this) => key is NewKey, thisArg: This, - ): [Collection, Collection, V>]; - public partition( - fn: (this: This, value: V, key: K, collection: this) => value is V2, + ): [Collection, Collection, Value>]; + public partition( + fn: (this: This, value: Value, key: Key, collection: this) => value is NewValue, thisArg: This, - ): [Collection, Collection>]; + ): [Collection, Collection>]; public partition( - fn: (this: This, value: V, key: K, collection: this) => unknown, + fn: (this: This, value: Value, key: Key, collection: this) => unknown, thisArg: This, - ): [Collection, Collection]; + ): [Collection, Collection]; public partition( - fn: (value: V, key: K, collection: this) => unknown, + fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown, - ): [Collection, Collection] { + ): [Collection, Collection] { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); - const results: [Collection, Collection] = [ - new this.constructor[Symbol.species](), - new this.constructor[Symbol.species](), + const results: [Collection, Collection] = [ + new this.constructor[Symbol.species](), + new this.constructor[Symbol.species](), ]; for (const [key, val] of this) { if (fn(val, key, this)) { @@ -449,15 +475,20 @@ export class Collection extends Map { * collection.flatMap(guild => guild.members.cache); * ``` */ - public flatMap(fn: (value: V, key: K, collection: this) => Collection): Collection; - public flatMap( - fn: (this: This, value: V, key: K, collection: this) => Collection, + public flatMap( + fn: (value: Value, key: Key, collection: this) => Collection, + ): Collection; + public flatMap( + fn: (this: This, value: Value, key: Key, collection: this) => Collection, thisArg: This, - ): Collection; - public flatMap(fn: (value: V, key: K, collection: this) => Collection, thisArg?: unknown): Collection { + ): Collection; + public flatMap( + fn: (value: Value, key: Key, collection: this) => Collection, + thisArg?: unknown, + ): Collection { // eslint-disable-next-line unicorn/no-array-method-this-argument const collections = this.map(fn, thisArg); - return new this.constructor[Symbol.species]().concat(...collections); + return new this.constructor[Symbol.species]().concat(...collections); } /** @@ -471,13 +502,16 @@ export class Collection extends Map { * collection.map(user => user.tag); * ``` */ - public map(fn: (value: V, key: K, collection: this) => T): T[]; - public map(fn: (this: This, value: V, key: K, collection: this) => T, thisArg: This): T[]; - public map(fn: (value: V, key: K, collection: this) => T, thisArg?: unknown): T[] { + public map(fn: (value: Value, key: Key, collection: this) => NewValue): NewValue[]; + public map( + fn: (this: This, value: Value, key: Key, collection: this) => NewValue, + thisArg: This, + ): NewValue[]; + public map(fn: (value: Value, key: Key, collection: this) => NewValue, thisArg?: unknown): NewValue[] { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); const iter = this.entries(); - return Array.from({ length: this.size }, (): T => { + return Array.from({ length: this.size }, (): NewValue => { const [key, value] = iter.next().value; return fn(value, key, this); }); @@ -494,12 +528,18 @@ export class Collection extends Map { * collection.mapValues(user => user.tag); * ``` */ - public mapValues(fn: (value: V, key: K, collection: this) => T): Collection; - public mapValues(fn: (this: This, value: V, key: K, collection: this) => T, thisArg: This): Collection; - public mapValues(fn: (value: V, key: K, collection: this) => T, thisArg?: unknown): Collection { + public mapValues(fn: (value: Value, key: Key, collection: this) => NewValue): Collection; + public mapValues( + fn: (this: This, value: Value, key: Key, collection: this) => NewValue, + thisArg: This, + ): Collection; + public mapValues( + fn: (value: Value, key: Key, collection: this) => NewValue, + thisArg?: unknown, + ): Collection { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); - const coll = new this.constructor[Symbol.species](); + const coll = new this.constructor[Symbol.species](); for (const [key, val] of this) coll.set(key, fn(val, key, this)); return coll; } @@ -515,9 +555,9 @@ export class Collection extends Map { * collection.some(user => user.discriminator === '0000'); * ``` */ - public some(fn: (value: V, key: K, collection: this) => unknown): boolean; - public some(fn: (this: T, value: V, key: K, collection: this) => unknown, thisArg: T): boolean; - public some(fn: (value: V, key: K, collection: this) => unknown, thisArg?: unknown): boolean { + public some(fn: (value: Value, key: Key, collection: this) => unknown): boolean; + public some(fn: (this: This, value: Value, key: Key, collection: this) => unknown, thisArg: This): boolean; + public some(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): boolean { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); for (const [key, val] of this) { @@ -538,19 +578,23 @@ export class Collection extends Map { * collection.every(user => !user.bot); * ``` */ - public every(fn: (value: V, key: K, collection: this) => key is K2): this is Collection; - public every(fn: (value: V, key: K, collection: this) => value is V2): this is Collection; - public every(fn: (value: V, key: K, collection: this) => unknown): boolean; - public every( - fn: (this: This, value: V, key: K, collection: this) => key is K2, + public every( + fn: (value: Value, key: Key, collection: this) => key is NewKey, + ): this is Collection; + public every( + fn: (value: Value, key: Key, collection: this) => value is NewValue, + ): this is Collection; + public every(fn: (value: Value, key: Key, collection: this) => unknown): boolean; + public every( + fn: (this: This, value: Value, key: Key, collection: this) => key is NewKey, thisArg: This, - ): this is Collection; - public every( - fn: (this: This, value: V, key: K, collection: this) => value is V2, + ): this is Collection; + public every( + fn: (this: This, value: Value, key: Key, collection: this) => value is NewValue, thisArg: This, - ): this is Collection; - public every(fn: (this: This, value: V, key: K, collection: this) => unknown, thisArg: This): boolean; - public every(fn: (value: V, key: K, collection: this) => unknown, thisArg?: unknown): boolean { + ): this is Collection; + public every(fn: (this: This, value: Value, key: Key, collection: this) => unknown, thisArg: This): boolean; + public every(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): boolean { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); for (const [key, val] of this) { @@ -572,9 +616,12 @@ export class Collection extends Map { * collection.reduce((acc, guild) => acc + guild.memberCount, 0); * ``` */ - public reduce(fn: (accumulator: T, value: V, key: K, collection: this) => T, initialValue?: T): T { + public reduce( + fn: (accumulator: InitialValue, value: Value, key: Key, collection: this) => InitialValue, + initialValue?: InitialValue, + ): InitialValue { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); - let accumulator!: T; + let accumulator!: InitialValue; const iterator = this.entries(); if (initialValue === undefined) { @@ -598,15 +645,18 @@ export class Collection extends Map { * @param fn - Function used to reduce, taking four arguments; `accumulator`, `value`, `key`, and `collection` * @param initialValue - Starting value for the accumulator */ - public reduceRight(fn: (accumulator: T, value: V, key: K, collection: this) => T, initialValue?: T): T { + public reduceRight( + fn: (accumulator: InitialValue, value: Value, key: Key, collection: this) => InitialValue, + initialValue?: InitialValue, + ): InitialValue { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); const entries = [...this.entries()]; - let accumulator!: T; + let accumulator!: InitialValue; let index: number; if (initialValue === undefined) { if (entries.length === 0) throw new TypeError('Reduce of empty collection with no initial value'); - accumulator = entries[entries.length - 1]![1] as unknown as T; + accumulator = entries[entries.length - 1]![1] as unknown as InitialValue; index = entries.length - 1; } else { accumulator = initialValue; @@ -637,9 +687,9 @@ export class Collection extends Map { * .each(user => console.log(user.username)); * ``` */ - public each(fn: (value: V, key: K, collection: this) => void): this; - public each(fn: (this: T, value: V, key: K, collection: this) => void, thisArg: T): this; - public each(fn: (value: V, key: K, collection: this) => void, thisArg?: unknown): this { + public each(fn: (value: Value, key: Key, collection: this) => void): this; + public each(fn: (this: This, value: Value, key: Key, collection: this) => void, thisArg: This): this; + public each(fn: (value: Value, key: Key, collection: this) => void, thisArg?: unknown): this { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); @@ -664,7 +714,7 @@ export class Collection extends Map { * ``` */ public tap(fn: (collection: this) => void): this; - public tap(fn: (this: T, collection: this) => void, thisArg: T): this; + public tap(fn: (this: This, collection: this) => void, thisArg: This): this; public tap(fn: (collection: this) => void, thisArg?: unknown): this { if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`); if (thisArg !== undefined) fn = fn.bind(thisArg); @@ -680,7 +730,7 @@ export class Collection extends Map { * const newColl = someColl.clone(); * ``` */ - public clone(): Collection { + public clone(): Collection { return new this.constructor[Symbol.species](this); } @@ -693,7 +743,7 @@ export class Collection extends Map { * const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl); * ``` */ - public concat(...collections: ReadonlyCollection[]) { + public concat(...collections: ReadonlyCollection[]) { const newColl = this.clone(); for (const coll of collections) { for (const [key, val] of coll) newColl.set(key, val); @@ -710,7 +760,7 @@ export class Collection extends Map { * @param collection - Collection to compare with * @returns Whether the collections have identical contents */ - public equals(collection: ReadonlyCollection) { + public equals(collection: ReadonlyCollection) { if (!collection) return false; // runtime check if (this === collection) return true; if (this.size !== collection.size) return false; @@ -735,7 +785,7 @@ export class Collection extends Map { * collection.sort((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); * ``` */ - public sort(compareFunction: Comparator = Collection.defaultSort) { + public sort(compareFunction: Comparator = Collection.defaultSort) { const entries = [...this.entries()]; entries.sort((a, b): number => compareFunction(a[1], b[1], a[0], b[0])); @@ -763,8 +813,8 @@ export class Collection extends Map { * // => Collection { 'a' => 1 } * ``` */ - public intersection(other: ReadonlyCollection): Collection { - const coll = new this.constructor[Symbol.species](); + public intersection(other: ReadonlyCollection): Collection { + const coll = new this.constructor[Symbol.species](); for (const [key, value] of this) { if (other.has(key)) coll.set(key, value); @@ -789,8 +839,8 @@ export class Collection extends Map { * // => Collection { 'a' => 1, 'b' => 2, 'c' => 3 } * ``` */ - public union(other: ReadonlyCollection): Collection { - const coll = new this.constructor[Symbol.species](this); + public union(other: ReadonlyCollection): Collection { + const coll = new this.constructor[Symbol.species](this); for (const [key, value] of other) { if (!coll.has(key)) coll.set(key, value); @@ -813,8 +863,8 @@ export class Collection extends Map { * // => Collection { 'c' => 3 } * ``` */ - public difference(other: ReadonlyCollection): Collection { - const coll = new this.constructor[Symbol.species](); + public difference(other: ReadonlyCollection): Collection { + const coll = new this.constructor[Symbol.species](); for (const [key, value] of this) { if (!other.has(key)) coll.set(key, value); @@ -836,8 +886,10 @@ export class Collection extends Map { * // => Collection { 'b' => 2, 'c' => 3 } * ``` */ - public symmetricDifference(other: ReadonlyCollection): Collection { - const coll = new this.constructor[Symbol.species](); + public symmetricDifference( + other: ReadonlyCollection, + ): Collection { + const coll = new this.constructor[Symbol.species](); for (const [key, value] of this) { if (!other.has(key)) coll.set(key, value); @@ -878,13 +930,13 @@ export class Collection extends Map { * ); * ``` */ - public merge( - other: ReadonlyCollection, - whenInSelf: (value: V, key: K) => Keep, - whenInOther: (valueOther: T, key: K) => Keep, - whenInBoth: (value: V, valueOther: T, key: K) => Keep, - ): Collection { - const coll = new this.constructor[Symbol.species](); + public merge( + other: ReadonlyCollection, + whenInSelf: (value: Value, key: Key) => Keep, + whenInOther: (valueOther: OtherValue, key: Key) => Keep, + whenInBoth: (value: Value, valueOther: OtherValue, key: Key) => Keep, + ): Collection { + const coll = new this.constructor[Symbol.species](); const keys = new Set([...this.keys(), ...other.keys()]); for (const key of keys) { @@ -927,7 +979,7 @@ export class Collection extends Map { * collection.sorted((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); * ``` */ - public toSorted(compareFunction: Comparator = Collection.defaultSort) { + public toSorted(compareFunction: Comparator = Collection.defaultSort) { return new this.constructor[Symbol.species](this).sort((av, bv, ak, bk) => compareFunction(av, bv, ak, bk)); } @@ -936,7 +988,7 @@ export class Collection extends Map { return [...this.entries()]; } - private static defaultSort(firstValue: V, secondValue: V): number { + private static defaultSort(firstValue: Value, secondValue: Value): number { return Number(firstValue > secondValue) || Number(firstValue === secondValue) - 1; } @@ -951,11 +1003,11 @@ export class Collection extends Map { * // returns Collection { "a" => 3, "b" => 2 } * ``` */ - public static combineEntries( - entries: Iterable<[K, V]>, - combine: (firstValue: V, secondValue: V, key: K) => V, - ): Collection { - const coll = new Collection(); + public static combineEntries( + entries: Iterable<[Key, Value]>, + combine: (firstValue: Value, secondValue: Value, key: Key) => Value, + ): Collection { + const coll = new Collection(); for (const [key, value] of entries) { if (coll.has(key)) { coll.set(key, combine(coll.get(key)!, value, key)); @@ -971,9 +1023,9 @@ export class Collection extends Map { /** * @internal */ -export type Keep = { keep: false } | { keep: true; value: V }; +export type Keep = { keep: false } | { keep: true; value: Value }; /** * @internal */ -export type Comparator = (firstValue: V, secondValue: V, firstKey: K, secondKey: K) => number; +export type Comparator = (firstValue: Value, secondValue: Value, firstKey: Key, secondKey: Key) => number; diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts index 7cbb099a9b70..06252c855082 100644 --- a/packages/core/src/client.ts +++ b/packages/core/src/client.ts @@ -85,8 +85,8 @@ export interface IntrinsicProps { shardId: number; } -export interface WithIntrinsicProps extends IntrinsicProps { - data: T; +export interface WithIntrinsicProps extends IntrinsicProps { + data: Data; } export interface MappedEvents { @@ -332,7 +332,7 @@ export class Client extends AsyncEventEmitter { }); } - private wrapIntrinsicProps(obj: T, shardId: number): WithIntrinsicProps { + private wrapIntrinsicProps(obj: ObjectType, shardId: number): WithIntrinsicProps { return { api: this.api, shardId, diff --git a/packages/discord.js/.eslintignore b/packages/discord.js/.eslintignore deleted file mode 100644 index b91919e38cd0..000000000000 --- a/packages/discord.js/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -typings diff --git a/packages/discord.js/.eslintrc.json b/packages/discord.js/.eslintrc.json index ed7515f062ce..d2b656f1cdbe 100644 --- a/packages/discord.js/.eslintrc.json +++ b/packages/discord.js/.eslintrc.json @@ -1,200 +1,223 @@ { "$schema": "https://json.schemastore.org/eslintrc.json", "root": true, - "extends": ["eslint:recommended"], - "plugins": ["import"], - "parserOptions": { - "ecmaVersion": 2022 - }, - "env": { - "es2022": true, - "node": true - }, - "rules": { - "import/order": [ - "error", - { - "groups": ["builtin", "external", "internal", "index", "sibling", "parent"], - "alphabetize": { - "order": "asc" - } - } - ], - "strict": ["error", "global"], - "no-await-in-loop": "warn", - "no-compare-neg-zero": "error", - "no-template-curly-in-string": "error", - "no-unsafe-negation": "error", - "valid-jsdoc": [ - "error", - { - "requireReturn": false, - "requireReturnDescription": false, - "prefer": { - "return": "returns", - "arg": "param" - }, - "preferType": { - "String": "string", - "Number": "number", - "Boolean": "boolean", - "Symbol": "symbol", - "object": "Object", - "function": "Function", - "array": "Array", - "date": "Date", - "error": "Error", - "null": "void" - } - } - ], + "overrides": [ + { + "files": ["src/**/*.js"], + "extends": ["eslint:recommended"], + "plugins": ["import"], + "parserOptions": { + "ecmaVersion": 2022 + }, + "env": { + "es2022": true, + "node": true + }, + "rules": { + "import/order": [ + "error", + { + "groups": ["builtin", "external", "internal", "index", "sibling", "parent"], + "alphabetize": { + "order": "asc" + } + } + ], + "strict": ["error", "global"], + "no-await-in-loop": "warn", + "no-compare-neg-zero": "error", + "no-template-curly-in-string": "error", + "no-unsafe-negation": "error", + "valid-jsdoc": [ + "error", + { + "requireReturn": false, + "requireReturnDescription": false, + "prefer": { + "return": "returns", + "arg": "param" + }, + "preferType": { + "String": "string", + "Number": "number", + "Boolean": "boolean", + "Symbol": "symbol", + "object": "Object", + "function": "Function", + "array": "Array", + "date": "Date", + "error": "Error", + "null": "void" + } + } + ], - "accessor-pairs": "warn", - "array-callback-return": "error", - "consistent-return": "error", - "curly": ["error", "multi-line", "consistent"], - "dot-location": ["error", "property"], - "dot-notation": "error", - "eqeqeq": "error", - "no-empty-function": "error", - "no-floating-decimal": "error", - "no-implied-eval": "error", - "no-invalid-this": "error", - "no-lone-blocks": "error", - "no-multi-spaces": "error", - "no-new-func": "error", - "no-new-wrappers": "error", - "no-new": "error", - "no-octal-escape": "error", - "no-return-assign": "error", - "no-return-await": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-throw-literal": "error", - "no-unmodified-loop-condition": "error", - "no-unused-expressions": "error", - "no-useless-call": "error", - "no-useless-concat": "error", - "no-useless-escape": "error", - "no-useless-return": "error", - "no-void": "error", - "no-warning-comments": "warn", - "prefer-promise-reject-errors": "error", - "require-await": "warn", - "wrap-iife": "error", - "yoda": "error", + "accessor-pairs": "warn", + "array-callback-return": "error", + "consistent-return": "error", + "curly": ["error", "multi-line", "consistent"], + "dot-location": ["error", "property"], + "dot-notation": "error", + "eqeqeq": "error", + "no-empty-function": "error", + "no-floating-decimal": "error", + "no-implied-eval": "error", + "no-invalid-this": "error", + "no-lone-blocks": "error", + "no-multi-spaces": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-new": "error", + "no-octal-escape": "error", + "no-return-assign": "error", + "no-return-await": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-throw-literal": "error", + "no-unmodified-loop-condition": "error", + "no-unused-expressions": "error", + "no-useless-call": "error", + "no-useless-concat": "error", + "no-useless-escape": "error", + "no-useless-return": "error", + "no-void": "error", + "no-warning-comments": "warn", + "prefer-promise-reject-errors": "error", + "require-await": "warn", + "wrap-iife": "error", + "yoda": "error", - "no-label-var": "error", - "no-shadow": "error", - "no-undef-init": "error", + "no-label-var": "error", + "no-shadow": "error", + "no-undef-init": "error", - "callback-return": "error", - "getter-return": "off", - "handle-callback-err": "error", - "no-mixed-requires": "error", - "no-new-require": "error", - "no-path-concat": "error", + "callback-return": "error", + "getter-return": "off", + "handle-callback-err": "error", + "no-mixed-requires": "error", + "no-new-require": "error", + "no-path-concat": "error", - "array-bracket-spacing": "error", - "block-spacing": "error", - "brace-style": ["error", "1tbs", { "allowSingleLine": true }], - "capitalized-comments": ["error", "always", { "ignoreConsecutiveComments": true }], - "comma-dangle": ["error", "always-multiline"], - "comma-spacing": "error", - "comma-style": "error", - "computed-property-spacing": "error", - "consistent-this": ["error", "$this"], - "eol-last": "error", - "func-names": "error", - "func-name-matching": "error", - "func-style": ["error", "declaration", { "allowArrowFunctions": true }], - "key-spacing": "error", - "keyword-spacing": "error", - "max-depth": "error", - "max-len": ["error", 120, 2], - "max-nested-callbacks": ["error", { "max": 4 }], - "max-statements-per-line": ["error", { "max": 2 }], - "new-cap": "off", - "newline-per-chained-call": ["error", { "ignoreChainWithDepth": 3 }], - "no-array-constructor": "error", - "no-inline-comments": "error", - "no-lonely-if": "error", - "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }], - "no-new-object": "error", - "no-spaced-func": "error", - "no-trailing-spaces": "error", - "no-unneeded-ternary": "error", - "no-whitespace-before-property": "error", - "nonblock-statement-body-position": "error", - "object-curly-spacing": ["error", "always"], - "operator-assignment": "error", - "padded-blocks": ["error", "never"], - "quote-props": ["error", "as-needed"], - "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], - "semi-spacing": "error", - "semi": "error", - "space-before-blocks": "error", - "space-before-function-paren": [ - "error", - { - "anonymous": "never", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": "error", - "space-infix-ops": "error", - "space-unary-ops": "error", - "spaced-comment": "error", - "template-tag-spacing": "error", - "unicode-bom": "error", + "array-bracket-spacing": "error", + "block-spacing": "error", + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "capitalized-comments": ["error", "always", { "ignoreConsecutiveComments": true }], + "comma-dangle": ["error", "always-multiline"], + "comma-spacing": "error", + "comma-style": "error", + "computed-property-spacing": "error", + "consistent-this": ["error", "$this"], + "eol-last": "error", + "func-names": "error", + "func-name-matching": "error", + "func-style": ["error", "declaration", { "allowArrowFunctions": true }], + "key-spacing": "error", + "keyword-spacing": "error", + "max-depth": "error", + "max-len": ["error", 120, 2], + "max-nested-callbacks": ["error", { "max": 4 }], + "max-statements-per-line": ["error", { "max": 2 }], + "new-cap": "off", + "newline-per-chained-call": ["error", { "ignoreChainWithDepth": 3 }], + "no-array-constructor": "error", + "no-inline-comments": "error", + "no-lonely-if": "error", + "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }], + "no-new-object": "error", + "no-spaced-func": "error", + "no-trailing-spaces": "error", + "no-unneeded-ternary": "error", + "no-whitespace-before-property": "error", + "nonblock-statement-body-position": "error", + "object-curly-spacing": ["error", "always"], + "operator-assignment": "error", + "padded-blocks": ["error", "never"], + "quote-props": ["error", "as-needed"], + "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], + "semi-spacing": "error", + "semi": "error", + "space-before-blocks": "error", + "space-before-function-paren": [ + "error", + { + "anonymous": "never", + "named": "never", + "asyncArrow": "always" + } + ], + "space-in-parens": "error", + "space-infix-ops": "error", + "space-unary-ops": "error", + "spaced-comment": "error", + "template-tag-spacing": "error", + "unicode-bom": "error", - "arrow-body-style": "error", - "arrow-parens": ["error", "as-needed"], - "arrow-spacing": "error", - "no-duplicate-imports": "error", - "no-useless-computed-key": "error", - "no-useless-constructor": "error", - "prefer-arrow-callback": "error", - "prefer-numeric-literals": "error", - "prefer-rest-params": "error", - "prefer-spread": "error", - "prefer-template": "error", - "prefer-object-has-own": "error", - "rest-spread-spacing": "error", - "template-curly-spacing": "error", - "yield-star-spacing": "error", + "arrow-body-style": "error", + "arrow-parens": ["error", "as-needed"], + "arrow-spacing": "error", + "no-duplicate-imports": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "error", + "prefer-arrow-callback": "error", + "prefer-numeric-literals": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + "prefer-object-has-own": "error", + "rest-spread-spacing": "error", + "template-curly-spacing": "error", + "yield-star-spacing": "error", - "no-restricted-globals": [ - "error", - { - "name": "Buffer", - "message": "Import Buffer from `node:buffer` instead" - }, - { - "name": "process", - "message": "Import process from `node:process` instead" - }, - { - "name": "setTimeout", - "message": "Import setTimeout from `node:timers` instead" - }, - { - "name": "setInterval", - "message": "Import setInterval from `node:timers` instead" - }, - { - "name": "setImmediate", - "message": "Import setImmediate from `node:timers` instead" - }, - { - "name": "clearTimeout", - "message": "Import clearTimeout from `node:timers` instead" - }, - { - "name": "clearInterval", - "message": "Import clearInterval from `node:timers` instead" + "no-restricted-globals": [ + "error", + { + "name": "Buffer", + "message": "Import Buffer from `node:buffer` instead" + }, + { + "name": "process", + "message": "Import process from `node:process` instead" + }, + { + "name": "setTimeout", + "message": "Import setTimeout from `node:timers` instead" + }, + { + "name": "setInterval", + "message": "Import setInterval from `node:timers` instead" + }, + { + "name": "setImmediate", + "message": "Import setImmediate from `node:timers` instead" + }, + { + "name": "clearTimeout", + "message": "Import clearTimeout from `node:timers` instead" + }, + { + "name": "clearInterval", + "message": "Import clearInterval from `node:timers` instead" + } + ] + } + }, + { + "files": ["typings/*.ts"], + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "rules": { + "@typescript-eslint/naming-convention": [ + 2, + { + "selector": "typeParameter", + "format": ["PascalCase"], + "custom": { + "regex": "^\\w{3,}", + "match": true + } + } + ] } - ] - } + } + ] } diff --git a/packages/discord.js/package.json b/packages/discord.js/package.json index 02ac5839f13f..5eb07b37d41e 100644 --- a/packages/discord.js/package.json +++ b/packages/discord.js/package.json @@ -6,7 +6,7 @@ "scripts": { "test": "pnpm run docs:test && pnpm run test:typescript", "test:typescript": "tsc --noEmit && tsd", - "lint": "prettier --check . && tslint typings/index.d.ts && cross-env ESLINT_USE_FLAT_CONFIG=false eslint --format=pretty src", + "lint": "prettier --check . && tslint typings/index.d.ts && cross-env ESLINT_USE_FLAT_CONFIG=false eslint --format=pretty src typings", "format": "prettier --write . && cross-env ESLINT_USE_FLAT_CONFIG=false eslint --fix --format=pretty src", "fmt": "pnpm run format", "docs": "docgen -i './src/*.js' './src/**/*.js' -c ./docs/index.json -r ../../ -o ./docs/docs.json && pnpm run docs:new", @@ -72,6 +72,8 @@ "@discordjs/docgen": "workspace:^", "@favware/cliff-jumper": "2.2.1", "@types/node": "16.18.60", + "@typescript-eslint/eslint-plugin": "^6.10.0", + "@typescript-eslint/parser": "^6.10.0", "cross-env": "^7.0.3", "dtslint": "4.2.1", "eslint": "8.53.0", diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 8265c709e702..7e4ed80ea882 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -234,14 +234,14 @@ import { declare module 'node:events' { class EventEmitter { // Add type overloads for client events. - public static once( - eventEmitter: E, - eventName: E extends Client ? K : string, - ): Promise; - public static on( - eventEmitter: E, - eventName: E extends Client ? K : string, - ): AsyncIterableIterator; + public static once( + eventEmitter: Emitter, + eventName: Emitter extends Client ? Event : string, + ): Promise; + public static on( + eventEmitter: Emitter, + eventName: Emitter extends Client ? Events : string, + ): AsyncIterableIterator; } } @@ -296,23 +296,25 @@ export type ActionRowComponentData = MessageActionRowComponentData | ModalAction export type ActionRowComponent = MessageActionRowComponent | ModalActionRowComponent; -export interface ActionRowData | ActionRowComponentData> +export interface ActionRowData | ActionRowComponentData> extends BaseComponentData { - components: T[]; + components: ComponentType[]; } -export class ActionRowBuilder extends BuilderActionRow { +export class ActionRowBuilder< + ComponentType extends AnyComponentBuilder = AnyComponentBuilder, +> extends BuilderActionRow { constructor( data?: Partial< | ActionRowData> | APIActionRowComponent >, ); - public static from( + public static from( other: - | JSONEncodable>> - | APIActionRowComponent>, - ): ActionRowBuilder; + | JSONEncodable>> + | APIActionRowComponent>, + ): ActionRowBuilder; } export type MessageActionRowComponent = @@ -324,12 +326,12 @@ export type MessageActionRowComponent = | ChannelSelectMenuComponent; export type ModalActionRowComponent = TextInputComponent; -export class ActionRow extends Component< +export class ActionRow extends Component< APIActionRowComponent > { private constructor(data: APIActionRowComponent); - public readonly components: T[]; - public toJSON(): APIActionRowComponent>; + public readonly components: ComponentType[]; + public toJSON(): APIActionRowComponent>; } export class ActivityFlagsBitField extends BitField { @@ -527,7 +529,7 @@ export type GuildCacheMessage = CacheTypeReducer< Message | APIMessage >; -export type BooleanCache = T extends 'cached' ? true : false; +export type BooleanCache = Cached extends 'cached' ? true : false; export abstract class CommandInteraction extends BaseInteraction { public type: InteractionType.ApplicationCommand; @@ -595,12 +597,12 @@ export class InteractionResponse { public id: Snowflake; public get createdAt(): Date; public get createdTimestamp(): number; - public awaitMessageComponent( - options?: AwaitMessageCollectorOptionsParams, - ): Promise[T]>; - public createMessageComponentCollector( - options?: MessageCollectorOptionsParams, - ): InteractionCollector[T]>; + public awaitMessageComponent( + options?: AwaitMessageCollectorOptionsParams, + ): Promise[ComponentType]>; + public createMessageComponentCollector( + options?: MessageCollectorOptionsParams, + ): InteractionCollector[ComponentType]>; public delete(): Promise; public edit(options: string | MessagePayload | WebhookMessageEditOptions): Promise; public fetch(): Promise; @@ -676,23 +678,23 @@ export class BaseGuildVoiceChannel extends TextBasedChannelMixin(GuildChannel, t public setVideoQualityMode(videoQualityMode: VideoQualityMode, reason?: string): Promise; } -export type EnumLike = Record; - -export class BitField { - public constructor(bits?: BitFieldResolvable); - public bitfield: N; - public add(...bits: BitFieldResolvable[]): BitField; - public any(bit: BitFieldResolvable): boolean; - public equals(bit: BitFieldResolvable): boolean; - public freeze(): Readonly>; - public has(bit: BitFieldResolvable): boolean; - public missing(bits: BitFieldResolvable, ...hasParams: readonly unknown[]): S[]; - public remove(...bits: BitFieldResolvable[]): BitField; - public serialize(...hasParams: readonly unknown[]): Record; - public toArray(...hasParams: readonly unknown[]): S[]; - public toJSON(): N extends number ? number : string; - public valueOf(): N; - public [Symbol.iterator](): IterableIterator; +export type EnumLike = Record; + +export class BitField { + public constructor(bits?: BitFieldResolvable); + public bitfield: Type; + public add(...bits: BitFieldResolvable[]): BitField; + public any(bit: BitFieldResolvable): boolean; + public equals(bit: BitFieldResolvable): boolean; + public freeze(): Readonly>; + public has(bit: BitFieldResolvable): boolean; + public missing(bits: BitFieldResolvable, ...hasParams: readonly unknown[]): Flags[]; + public remove(...bits: BitFieldResolvable[]): BitField; + public serialize(...hasParams: readonly unknown[]): Record; + public toArray(...hasParams: readonly unknown[]): Flags[]; + public toJSON(): Type extends number ? number : string; + public valueOf(): Type; + public [Symbol.iterator](): IterableIterator; public static Flags: EnumLike; public static resolve(bit?: BitFieldResolvable): number | bigint; } @@ -717,11 +719,11 @@ export type AnyComponent = | APIModalComponent | APIActionRowComponent; -export class Component { - public readonly data: Readonly; - public get type(): T['type']; - public toJSON(): T; - public equals(other: this | T): boolean; +export class Component { + public readonly data: Readonly; + public get type(): RawComponentData['type']; + public toJSON(): RawComponentData; + public equals(other: this | RawComponentData): boolean; } export class ButtonComponent extends Component { @@ -948,7 +950,11 @@ export abstract class BaseChannel extends Base { public toString(): ChannelMention | UserMention; } -export type If = T extends true ? A : T extends false ? B : A | B; +export type If = Value extends true + ? TrueResult + : Value extends false + ? FalseResult + : TrueResult | FalseResult; export class Client extends BaseClient { public constructor(options: ClientOptions); @@ -992,29 +998,38 @@ export class Client extends BaseClient { public isReady(): this is Client; public toJSON(): unknown; - public on(event: K, listener: (...args: ClientEvents[K]) => Awaitable): this; - public on( - event: Exclude, + public on( + event: Event, + listener: (...args: ClientEvents[Event]) => Awaitable, + ): this; + public on( + event: Exclude, listener: (...args: any[]) => Awaitable, ): this; - public once(event: K, listener: (...args: ClientEvents[K]) => Awaitable): this; - public once( - event: Exclude, + public once( + event: Event, + listener: (...args: ClientEvents[Event]) => Awaitable, + ): this; + public once( + event: Exclude, listener: (...args: any[]) => Awaitable, ): this; - public emit(event: K, ...args: ClientEvents[K]): boolean; - public emit(event: Exclude, ...args: unknown[]): boolean; + public emit(event: Event, ...args: ClientEvents[Event]): boolean; + public emit(event: Exclude, ...args: unknown[]): boolean; - public off(event: K, listener: (...args: ClientEvents[K]) => Awaitable): this; - public off( - event: Exclude, + public off( + event: Event, + listener: (...args: ClientEvents[Event]) => Awaitable, + ): this; + public off( + event: Exclude, listener: (...args: any[]) => Awaitable, ): this; - public removeAllListeners(event?: K): this; - public removeAllListeners(event?: Exclude): this; + public removeAllListeners(event?: Event): this; + public removeAllListeners(event?: Exclude): this; } export class ClientApplication extends Application { @@ -1083,48 +1098,48 @@ export class ClientVoiceManager { export { Collection } from '@discordjs/collection'; -export interface CollectorEventTypes { - collect: [V, ...F]; - ignore: [V, ...F]; - dispose: [V, ...F]; - end: [collected: Collection, reason: string]; +export interface CollectorEventTypes { + collect: [Value, ...Extras]; + ignore: [Value, ...Extras]; + dispose: [Value, ...Extras]; + end: [collected: Collection, reason: string]; } -export abstract class Collector extends EventEmitter { - protected constructor(client: Client, options?: CollectorOptions<[V, ...F]>); +export abstract class Collector extends EventEmitter { + protected constructor(client: Client, options?: CollectorOptions<[Value, ...Extras]>); private _timeout: NodeJS.Timeout | null; private _idletimeout: NodeJS.Timeout | null; private _endReason: string | null; public readonly client: Client; - public collected: Collection; + public collected: Collection; public lastCollectedTimestamp: number | null; public get lastCollectedAt(): Date | null; public ended: boolean; public get endReason(): string | null; - public filter: CollectorFilter<[V, ...F]>; - public get next(): Promise; - public options: CollectorOptions<[V, ...F]>; + public filter: CollectorFilter<[Value, ...Extras]>; + public get next(): Promise; + public options: CollectorOptions<[Value, ...Extras]>; public checkEnd(): boolean; public handleCollect(...args: unknown[]): Promise; public handleDispose(...args: unknown[]): Promise; public stop(reason?: string): void; public resetTimer(options?: CollectorResetTimerOptions): void; - public [Symbol.asyncIterator](): AsyncIterableIterator<[V, ...F]>; + public [Symbol.asyncIterator](): AsyncIterableIterator<[Value, ...Extras]>; public toJSON(): unknown; protected listener: (...args: any[]) => void; - public abstract collect(...args: unknown[]): K | null | Promise; - public abstract dispose(...args: unknown[]): K | null; + public abstract collect(...args: unknown[]): Key | null | Promise; + public abstract dispose(...args: unknown[]): Key | null; - public on>( + public on>( event: EventKey, - listener: (...args: CollectorEventTypes[EventKey]) => Awaitable, + listener: (...args: CollectorEventTypes[EventKey]) => Awaitable, ): this; - public once>( + public once>( event: EventKey, - listener: (...args: CollectorEventTypes[EventKey]) => Awaitable, + listener: (...args: CollectorEventTypes[EventKey]) => Awaitable, ): this; } @@ -1190,34 +1205,34 @@ export class CommandInteractionOptionResolver( + public getChannel( name: string, required: true, - channelTypes?: readonly T[], + channelTypes?: readonly Type[], ): Extract< NonNullable['channel']>, { // The `type` property of the PublicThreadChannel class is typed as `ChannelType.PublicThread | ChannelType.AnnouncementThread` // If the user only passed one of those channel types, the Extract<> would have resolved to `never` // Hence the need for this ternary - type: T extends ChannelType.PublicThread | ChannelType.AnnouncementThread + type: Type extends ChannelType.PublicThread | ChannelType.AnnouncementThread ? ChannelType.PublicThread | ChannelType.AnnouncementThread - : T; + : Type; } >; - public getChannel( + public getChannel( name: string, required?: boolean, - channelTypes?: readonly T[], + channelTypes?: readonly Type[], ): Extract< NonNullable['channel']>, { // The `type` property of the PublicThreadChannel class is typed as `ChannelType.PublicThread | ChannelType.AnnouncementThread` // If the user only passed one of those channel types, the Extract<> would have resolved to `never` // Hence the need for this ternary - type: T extends ChannelType.PublicThread | ChannelType.AnnouncementThread + type: Type extends ChannelType.PublicThread | ChannelType.AnnouncementThread ? ChannelType.PublicThread | ChannelType.AnnouncementThread - : T; + : Type; } > | null; public getString(name: string, required: true): string; @@ -1382,9 +1397,9 @@ export class Guild extends AnonymousGuild { public editOnboarding(options: GuildOnboardingEditOptions): Promise; public editWelcomeScreen(options: WelcomeScreenEditOptions): Promise; public equals(guild: Guild): boolean; - public fetchAuditLogs( - options?: GuildAuditLogsFetchOptions, - ): Promise>; + public fetchAuditLogs( + options?: GuildAuditLogsFetchOptions, + ): Promise>; public fetchIntegrations(): Promise>; public fetchOnboarding(): Promise; public fetchOwner(options?: BaseFetchOptions): Promise; @@ -1430,14 +1445,14 @@ export class Guild extends AnonymousGuild { public toJSON(): unknown; } -export class GuildAuditLogs { +export class GuildAuditLogs { private constructor(guild: Guild, data: RawGuildAuditLogData); private applicationCommands: Collection; private webhooks: Collection; private integrations: Collection; private guildScheduledEvents: Collection; private autoModerationRules: Collection; - public entries: Collection>; + public entries: Collection>; public toJSON(): unknown; } @@ -1657,7 +1672,7 @@ export class GuildPreview extends Base { public toString(): string; } -export class GuildScheduledEvent extends Base { +export class GuildScheduledEvent extends Base { private constructor(client: Client, data: RawGuildScheduledEventData); public id: Snowflake; public guildId: Snowflake; @@ -1668,7 +1683,7 @@ export class GuildScheduledEvent): string | null; public createInviteURL(options?: GuildScheduledEventInviteURLCreateOptions): Promise; - public edit>( - options: GuildScheduledEventEditOptions, - ): Promise>; - public fetch(force?: boolean): Promise>; - public delete(): Promise>; - public setName(name: string, reason?: string): Promise>; - public setScheduledStartTime(scheduledStartTime: DateResolvable, reason?: string): Promise>; - public setScheduledEndTime(scheduledEndTime: DateResolvable, reason?: string): Promise>; - public setDescription(description: string, reason?: string): Promise>; - public setStatus>( - status: T, + public edit>( + options: GuildScheduledEventEditOptions, + ): Promise>; + public fetch(force?: boolean): Promise>; + public delete(): Promise>; + public setName(name: string, reason?: string): Promise>; + public setScheduledStartTime( + scheduledStartTime: DateResolvable, + reason?: string, + ): Promise>; + public setScheduledEndTime(scheduledEndTime: DateResolvable, reason?: string): Promise>; + public setDescription(description: string, reason?: string): Promise>; + public setStatus>( + status: AcceptableStatus, reason?: string, - ): Promise>; - public setLocation(location: string, reason?: string): Promise>; - public fetchSubscribers( - options?: T, - ): Promise>; + ): Promise>; + public setLocation(location: string, reason?: string): Promise>; + public fetchSubscribers( + options?: Options, + ): Promise>; public toString(): string; public isActive(): this is GuildScheduledEvent; public isCanceled(): this is GuildScheduledEvent; @@ -1861,12 +1879,12 @@ export class BaseInteraction extends Base public isRepliable(): this is RepliableInteraction; } -export class InteractionCollector extends Collector< +export class InteractionCollector extends Collector< Snowflake, - T, - [Collection] + Interaction, + [Collection] > { - public constructor(client: Client, options?: InteractionCollectorOptions); + public constructor(client: Client, options?: InteractionCollectorOptions); private _handleMessageDeletion(message: Message): void; private _handleChannelDeletion(channel: NonThreadGuildBasedChannel): void; private _handleGuildDeletion(guild: Guild): void; @@ -1877,19 +1895,25 @@ export class InteractionCollector extends Collec public guildId: Snowflake | null; public interactionType: InteractionType | null; public messageId: Snowflake | null; - public options: InteractionCollectorOptions; + public options: InteractionCollectorOptions; public total: number; public users: Collection; public collect(interaction: Interaction): Snowflake; public empty(): void; public dispose(interaction: Interaction): Snowflake; - public on(event: 'collect' | 'dispose' | 'ignore', listener: (interaction: T) => Awaitable): this; - public on(event: 'end', listener: (collected: Collection, reason: string) => Awaitable): this; + public on(event: 'collect' | 'dispose' | 'ignore', listener: (interaction: Interaction) => Awaitable): this; + public on( + event: 'end', + listener: (collected: Collection, reason: string) => Awaitable, + ): this; public on(event: string, listener: (...args: any[]) => Awaitable): this; - public once(event: 'collect' | 'dispose' | 'ignore', listener: (interaction: T) => Awaitable): this; - public once(event: 'end', listener: (collected: Collection, reason: string) => Awaitable): this; + public once(event: 'collect' | 'dispose' | 'ignore', listener: (interaction: Interaction) => Awaitable): this; + public once( + event: 'end', + listener: (collected: Collection, reason: string) => Awaitable, + ): this; public once(event: string, listener: (...args: any[]) => Awaitable): this; } @@ -1954,25 +1978,37 @@ export class InviteGuild extends AnonymousGuild { public welcomeScreen: WelcomeScreen | null; } -export class LimitedCollection extends Collection { - public constructor(options?: LimitedCollectionOptions, iterable?: Iterable); +export class LimitedCollection extends Collection { + public constructor(options?: LimitedCollectionOptions, iterable?: Iterable); public maxSize: number; - public keepOverLimit: ((value: V, key: K, collection: this) => boolean) | null; + public keepOverLimit: ((value: Value, key: Key, collection: this) => boolean) | null; } export type MessageComponentType = Exclude; -export type MessageCollectorOptionsParams = { - componentType?: T; -} & MessageComponentCollectorOptions[T]>; +export type MessageCollectorOptionsParams< + ComponentType extends MessageComponentType, + Cached extends boolean = boolean, +> = { + componentType?: ComponentType; +} & MessageComponentCollectorOptions[ComponentType]>; -export type MessageChannelCollectorOptionsParams = { - componentType?: T; -} & MessageChannelComponentCollectorOptions[T]>; +export type MessageChannelCollectorOptionsParams< + ComponentType extends MessageComponentType, + Cached extends boolean = boolean, +> = { + componentType?: ComponentType; +} & MessageChannelComponentCollectorOptions[ComponentType]>; -export type AwaitMessageCollectorOptionsParams = { - componentType?: T; -} & Pick[T]>, keyof AwaitMessageComponentOptions>; +export type AwaitMessageCollectorOptionsParams< + ComponentType extends MessageComponentType, + Cached extends boolean = boolean, +> = { + componentType?: ComponentType; +} & Pick< + InteractionCollectorOptions[ComponentType]>, + keyof AwaitMessageComponentOptions +>; export interface StringMappedInteractionTypes { Button: ButtonInteraction; @@ -1984,7 +2020,7 @@ export interface StringMappedInteractionTypes; } -export type WrapBooleanCache = If; +export type WrapBooleanCache = If; export interface MappedInteractionTypes { [ComponentType.Button]: ButtonInteraction>; @@ -2043,14 +2079,14 @@ export class Message extends Base { public webhookId: Snowflake | null; public flags: Readonly; public reference: MessageReference | null; - public awaitMessageComponent( - options?: AwaitMessageCollectorOptionsParams, - ): Promise[T]>; + public awaitMessageComponent( + options?: AwaitMessageCollectorOptionsParams, + ): Promise[ComponentType]>; public awaitReactions(options?: AwaitReactionsOptions): Promise>; public createReactionCollector(options?: ReactionCollectorOptions): ReactionCollector; - public createMessageComponentCollector( - options?: MessageCollectorOptionsParams, - ): InteractionCollector[T]>; + public createMessageComponentCollector( + options?: MessageCollectorOptionsParams, + ): InteractionCollector[ComponentType]>; public delete(): Promise>; public edit(content: string | MessageEditOptions | MessagePayload): Promise>; public equals(message: Message, rawData: unknown): boolean; @@ -2310,7 +2346,7 @@ export class ModalSubmitFields { constructor(components: ModalActionRowComponent[][]); public components: ActionRowModalData[]; public fields: Collection; - public getField(customId: string, type: T): { type: T } & TextInputModalData; + public getField(customId: string, type: Type): { type: Type } & TextInputModalData; public getField(customId: string, type?: ComponentType): TextInputModalData; public getTextInputValue(customId: string): string; } @@ -2749,22 +2785,25 @@ export class Shard extends EventEmitter { public silent: boolean; public worker: Worker | null; public eval(script: string): Promise; - public eval(fn: (client: Client) => T): Promise; - public eval(fn: (client: Client, context: Serialized

) => T, context: P): Promise; + public eval(fn: (client: Client) => Result): Promise; + public eval( + fn: (client: Client, context: Serialized) => Result, + context: Context, + ): Promise; public fetchClientValue(prop: string): Promise; public kill(): void; public respawn(options?: { delay?: number; timeout?: number }): Promise; public send(message: unknown): Promise; public spawn(timeout?: number): Promise; - public on( - event: K, - listener: (...args: ShardEventTypes[K]) => Awaitable, + public on( + event: Event, + listener: (...args: ShardEventTypes[Event]) => Awaitable, ): this; - public once( - event: K, - listener: (...args: ShardEventTypes[K]) => Awaitable, + public once( + event: Event, + listener: (...args: ShardEventTypes[Event]) => Awaitable, ): this; } @@ -2780,16 +2819,19 @@ export class ShardClientUtil { public get ids(): number[]; public mode: ShardingManagerMode; public parentPort: MessagePort | null; - public broadcastEval(fn: (client: Client) => Awaitable): Promise[]>; - public broadcastEval(fn: (client: Client) => Awaitable, options: { shard: number }): Promise>; - public broadcastEval( - fn: (client: Client, context: Serialized

) => Awaitable, - options: { context: P }, - ): Promise[]>; - public broadcastEval( - fn: (client: Client, context: Serialized

) => Awaitable, - options: { context: P; shard: number }, - ): Promise>; + public broadcastEval(fn: (client: Client) => Awaitable): Promise[]>; + public broadcastEval( + fn: (client: Client) => Awaitable, + options: { shard: number }, + ): Promise>; + public broadcastEval( + fn: (client: Client, context: Serialized) => Awaitable, + options: { context: Context }, + ): Promise[]>; + public broadcastEval( + fn: (client: Client, context: Serialized) => Awaitable, + options: { context: Context; shard: number }, + ): Promise>; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; public respawnAll(options?: MultipleShardRespawnOptions): Promise; @@ -2813,16 +2855,19 @@ export class ShardingManager extends EventEmitter { public totalShards: number | 'auto'; public shardList: number[] | 'auto'; public broadcast(message: unknown): Promise; - public broadcastEval(fn: (client: Client) => Awaitable): Promise[]>; - public broadcastEval(fn: (client: Client) => Awaitable, options: { shard: number }): Promise>; - public broadcastEval( - fn: (client: Client, context: Serialized

) => Awaitable, - options: { context: P }, - ): Promise[]>; - public broadcastEval( - fn: (client: Client, context: Serialized

) => Awaitable, - options: { context: P; shard: number }, - ): Promise>; + public broadcastEval(fn: (client: Client) => Awaitable): Promise[]>; + public broadcastEval( + fn: (client: Client) => Awaitable, + options: { shard: number }, + ): Promise>; + public broadcastEval( + fn: (client: Client, context: Serialized) => Awaitable, + options: { context: Context }, + ): Promise[]>; + public broadcastEval( + fn: (client: Client, context: Serialized) => Awaitable, + options: { context: Context; shard: number }, + ): Promise>; public createShard(id: number): Shard; public fetchClientValues(prop: string): Promise; public fetchClientValues(prop: string, shard: number): Promise; @@ -2983,7 +3028,9 @@ export class Sweepers { public static expiredInviteSweepFilter( lifetime?: number, ): GlobalSweepFilter; - public static filterByLifetime(options?: LifetimeFilterOptions): GlobalSweepFilter; + public static filterByLifetime( + options?: LifetimeFilterOptions, + ): GlobalSweepFilter; public static outdatedMessageSweepFilter( lifetime?: number, ): GlobalSweepFilter; @@ -3197,9 +3244,9 @@ export class UserFlagsBitField extends BitField { export function basename(path: string, ext?: string): string; export function cleanContent(str: string, channel: TextBasedChannel): string; -export function discordSort( - collection: Collection, -): Collection; +export function discordSort( + collection: Collection, +): Collection; export function cleanCodeBlockContent(text: string): string; export function fetchRecommendedShardCount(token: string, options?: FetchRecommendedShardCountOptions): Promise; export function flatten(obj: unknown, ...props: Record[]): unknown; @@ -3211,11 +3258,11 @@ export function resolveColor(color: ColorResolvable): number; export function resolvePartialEmoji(emoji: Snowflake): PartialEmojiOnlyId; export function resolvePartialEmoji(emoji: Emoji | EmojiIdentifierResolvable): PartialEmoji | null; export function verifyString(data: string, error?: typeof Error, errorMessage?: string, allowEmpty?: boolean): string; -export function setPosition( - item: T, +export function setPosition( + item: Item, position: number, relative: boolean, - sorted: Collection, + sorted: Collection, client: Client, route: string, reason?: string, @@ -3254,15 +3301,15 @@ export interface ChannelCreateOptions { export function createChannel(client: Client, data: APIChannel, options?: ChannelCreateOptions): Channel; -export function createComponent( - data: APIMessageComponent & { type: T }, -): MappedComponentTypes[T]; -export function createComponent(data: C): C; +export function createComponent( + data: APIMessageComponent & { type: Type }, +): MappedComponentTypes[Type]; +export function createComponent(data: Data): Data; export function createComponent(data: APIMessageComponent | Component): Component; -export function createComponentBuilder( - data: APIMessageComponent & { type: T }, -): MappedComponentBuilderTypes[T]; -export function createComponentBuilder(data: C): C; +export function createComponentBuilder( + data: APIMessageComponent & { type: Type }, +): MappedComponentBuilderTypes[Type]; +export function createComponentBuilder(data: Data): Data; export function createComponentBuilder(data: APIMessageComponent | ComponentBuilder): ComponentBuilder; /** @deprecated This class is redundant as all methods of the class can be imported from discord.js directly. */ @@ -3463,14 +3510,14 @@ export class WebSocketShard extends EventEmitter { public send(data: unknown, important?: boolean): void; - public on( - event: K, - listener: (...args: WebSocketShardEventTypes[K]) => Awaitable, + public on( + event: Event, + listener: (...args: WebSocketShardEventTypes[Event]) => Awaitable, ): this; - public once( - event: K, - listener: (...args: WebSocketShardEventTypes[K]) => Awaitable, + public once( + event: Event, + listener: (...args: WebSocketShardEventTypes[Event]) => Awaitable, ): this; } @@ -3750,10 +3797,10 @@ export interface DiscordjsErrorFields { get code(): DiscordjsErrorCodes; } -export function DiscordjsErrorMixin( - Base: Constructable, - name: N, -): Constructable>; +export function DiscordjsErrorMixin( + Base: Constructable, + name: Name, +): Constructable>; export class DiscordjsError extends DiscordjsErrorMixin(Error, 'Error') {} @@ -3770,21 +3817,21 @@ export abstract class BaseManager { public readonly client: Client; } -export abstract class DataManager extends BaseManager { +export abstract class DataManager extends BaseManager { protected constructor(client: Client, holds: Constructable); public readonly holds: Constructable; - public get cache(): Collection; + public get cache(): Collection; public resolve(resolvable: Holds): Holds; - public resolve(resolvable: R): Holds | null; - public resolveId(resolvable: K | Holds): K; - public resolveId(resolvable: R): K | null; - public valueOf(): Collection; + public resolve(resolvable: Resolvable): Holds | null; + public resolveId(resolvable: Key | Holds): Key; + public resolveId(resolvable: Resolvable): Key | null; + public valueOf(): Collection; } -export abstract class CachedManager extends DataManager { +export abstract class CachedManager extends DataManager { protected constructor(client: Client, holds: Constructable, iterable?: Iterable); - private readonly _cache: Collection; - private _add(data: unknown, cache?: boolean, { id, extras }?: { id: K; extras: unknown[] }): Holds; + private readonly _cache: Collection; + private _add(data: unknown, cache?: boolean, { id, extras }?: { id: Key; extras: unknown[] }): Holds; } export type ApplicationCommandDataResolvable = @@ -3913,9 +3960,9 @@ export class CategoryChannelChildManager extends DataManager( - options: CategoryCreateChannelOptions & { type: T }, - ): Promise; + public create( + options: CategoryCreateChannelOptions & { type: Type }, + ): Promise; public create(options: CategoryCreateChannelOptions): Promise; } @@ -3960,9 +4007,9 @@ export class GuildChannelManager extends CachedManager; - public create( - options: GuildChannelCreateOptions & { type: T }, - ): Promise; + public create( + options: GuildChannelCreateOptions & { type: Type }, + ): Promise; public create(options: GuildChannelCreateOptions): Promise; public createWebhook(options: WebhookCreateOptions): Promise; public edit(channel: GuildChannelResolvable, data: GuildChannelEditOptions): Promise; @@ -4075,17 +4122,20 @@ export class GuildScheduledEventManager extends CachedManager< public create(options: GuildScheduledEventCreateOptions): Promise; public fetch(): Promise>; public fetch< - T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions, - >(options?: T): Promise>; - public edit>( + Options extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions, + >(options?: Options): Promise>; + public edit< + Status extends GuildScheduledEventStatus, + AcceptableStatus extends GuildScheduledEventSetStatusArg, + >( guildScheduledEvent: GuildScheduledEventResolvable, - options: GuildScheduledEventEditOptions, - ): Promise>; + options: GuildScheduledEventEditOptions, + ): Promise>; public delete(guildScheduledEvent: GuildScheduledEventResolvable): Promise; - public fetchSubscribers( + public fetchSubscribers( guildScheduledEvent: GuildScheduledEventResolvable, - options?: T, - ): Promise>; + options?: Options, + ): Promise>; } export class GuildStickerManager extends CachedManager { @@ -4294,20 +4344,20 @@ export class VoiceStateManager extends CachedManager = abstract new (...args: any[]) => T; -export function PartialTextBasedChannel( - Base?: Constructable, -): Constructable>; +export type Constructable = abstract new (...args: any[]) => Entity; +export function PartialTextBasedChannel( + Base?: Constructable, +): Constructable>; export function TextBasedChannelMixin< - T, + Entity, InGuild extends boolean = boolean, - I extends keyof TextBasedChannelFields = never, + IgnoredFields extends keyof TextBasedChannelFields = never, >( - Base?: Constructable, + Base?: Constructable, inGuild?: InGuild, - ignore?: I[], -): Constructable, I>>; + ignore?: IgnoredFields[], +): Constructable, IgnoredFields>>; export interface PartialTextBasedChannelFields { send(options: string | MessagePayload | MessageCreateOptions): Promise>; @@ -4320,17 +4370,17 @@ export interface TextBasedChannelFields lastPinTimestamp: number | null; get lastPinAt(): Date | null; messages: If; - awaitMessageComponent( - options?: AwaitMessageCollectorOptionsParams, - ): Promise; + awaitMessageComponent( + options?: AwaitMessageCollectorOptionsParams, + ): Promise; awaitMessages(options?: AwaitMessagesOptions): Promise>; bulkDelete( messages: Collection | readonly MessageResolvable[] | number, filterOld?: boolean, ): Promise>; - createMessageComponentCollector( - options?: MessageChannelCollectorOptionsParams, - ): InteractionCollector; + createMessageComponentCollector( + options?: MessageChannelCollectorOptionsParams, + ): InteractionCollector; createMessageCollector(options?: MessageCollectorOptions): MessageCollector; createWebhook(options: ChannelWebhookCreateOptions): Promise; fetchWebhooks(): Promise>; @@ -4339,8 +4389,8 @@ export interface TextBasedChannelFields setNSFW(nsfw?: boolean, reason?: string): Promise; } -export function PartialWebhookMixin(Base?: Constructable): Constructable; -export function WebhookMixin(Base?: Constructable): Constructable; +export function PartialWebhookMixin(Base?: Constructable): Constructable; +export function WebhookMixin(Base?: Constructable): Constructable; export interface PartialWebhookFields { id: Snowflake; @@ -4723,18 +4773,18 @@ export interface AutoModerationTriggerMetadata { mentionRaidProtectionEnabled: boolean; } -export type AwaitMessageComponentOptions = Omit< - MessageComponentCollectorOptions, +export type AwaitMessageComponentOptions = Omit< + MessageComponentCollectorOptions, 'max' | 'maxComponents' | 'maxUsers' >; -export type ModalSubmitInteractionCollectorOptions = Omit< - InteractionCollectorOptions, +export type ModalSubmitInteractionCollectorOptions = Omit< + InteractionCollectorOptions, 'channel' | 'message' | 'guild' | 'interactionType' >; -export type AwaitModalSubmitOptions = Omit< - ModalSubmitInteractionCollectorOptions, +export type AwaitModalSubmitOptions = Omit< + ModalSubmitInteractionCollectorOptions, 'max' | 'maxComponents' | 'maxUsers' > & { time: number; @@ -4764,12 +4814,12 @@ export interface BaseFetchOptions { force?: boolean; } -export type BitFieldResolvable = - | RecursiveReadonlyArray>> - | T - | N +export type BitFieldResolvable = + | RecursiveReadonlyArray>> + | Flags + | Type | `${bigint}` - | Readonly>; + | Readonly>; export type BufferResolvable = Buffer | string; @@ -4804,7 +4854,7 @@ export interface Caches { } export type CacheConstructors = { - [K in keyof Caches]: Caches[K][0] & { name: K }; + [Cache in keyof Caches]: Caches[Cache][0] & { name: Cache }; }; type OverriddenCaches = @@ -4819,11 +4869,11 @@ export type CacheFactory = ( managerType: CacheConstructors[Exclude], holds: Caches[(typeof manager)['name']][1], manager: CacheConstructors[keyof Caches], -) => (typeof manager)['prototype'] extends DataManager ? Collection : never; +) => (typeof manager)['prototype'] extends DataManager ? Collection : never; export type CacheWithLimitsOptions = { - [K in keyof Caches]?: Caches[K][0]['prototype'] extends DataManager - ? LimitedCollectionOptions | number + [K in keyof Caches]?: Caches[K][0]['prototype'] extends DataManager + ? LimitedCollectionOptions | number : never; }; @@ -5016,10 +5066,10 @@ export interface CloseEvent { reason: string; } -export type CollectorFilter = (...args: T) => boolean | Promise; +export type CollectorFilter = (...args: Arguments) => boolean | Promise; -export interface CollectorOptions { - filter?: CollectorFilter; +export interface CollectorOptions { + filter?: CollectorFilter; time?: number; idle?: number; dispose?: boolean; @@ -5408,7 +5458,9 @@ export interface AttachmentPayload { description?: string; } -export type GlobalSweepFilter = () => ((value: V, key: K, collection: Collection) => boolean) | null; +export type GlobalSweepFilter = () => + | ((value: Value, key: Key, collection: Collection) => boolean) + | null; interface GuildAuditLogsTypes { [AuditLogEvent.GuildUpdate]: ['Guild', 'Update']; @@ -5531,12 +5583,12 @@ export interface GuildAuditLogsEntryTargetField { +export interface GuildAuditLogsFetchOptions { before?: Snowflake | GuildAuditLogsEntry; after?: Snowflake | GuildAuditLogsEntry; limit?: number; user?: UserResolvable; - type?: T; + type?: Event; } export type GuildAuditLogsResolvable = AuditLogEvent | null; @@ -5747,11 +5799,11 @@ export interface GuildScheduledEventCreateOptions { } export interface GuildScheduledEventEditOptions< - S extends GuildScheduledEventStatus, - T extends GuildScheduledEventSetStatusArg, + Status extends GuildScheduledEventStatus, + AcceptableStatus extends GuildScheduledEventSetStatusArg, > extends Omit, 'channel'> { channel?: GuildVoiceChannelResolvable | null; - status?: T; + status?: AcceptableStatus; } export interface GuildScheduledEventEntityMetadata { @@ -5763,29 +5815,30 @@ export interface GuildScheduledEventEntityMetadataOptions { } export type GuildScheduledEventManagerFetchResult< - T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions, -> = T extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions + Options extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions | FetchGuildScheduledEventsOptions, +> = Options extends GuildScheduledEventResolvable | FetchGuildScheduledEventOptions ? GuildScheduledEvent : Collection; -export type GuildScheduledEventManagerFetchSubscribersResult = - T extends { withMember: true } - ? Collection> - : Collection>; +export type GuildScheduledEventManagerFetchSubscribersResult< + Options extends FetchGuildScheduledEventSubscribersOptions, +> = Options extends { withMember: true } + ? Collection> + : Collection>; export type GuildScheduledEventResolvable = Snowflake | GuildScheduledEvent; -export type GuildScheduledEventSetStatusArg = - T extends GuildScheduledEventStatus.Scheduled +export type GuildScheduledEventSetStatusArg = + Status extends GuildScheduledEventStatus.Scheduled ? GuildScheduledEventStatus.Active | GuildScheduledEventStatus.Canceled - : T extends GuildScheduledEventStatus.Active + : Status extends GuildScheduledEventStatus.Active ? GuildScheduledEventStatus.Completed : never; -export interface GuildScheduledEventUser { +export interface GuildScheduledEventUser { guildScheduledEventId: Snowflake; user: User; - member: T extends true ? GuildMember : null; + member: WithMember extends true ? GuildMember : null; } export type GuildTemplateResolvable = string; @@ -5837,8 +5890,10 @@ export type CollectedInteraction = | ButtonInteraction | ModalSubmitInteraction; -export interface InteractionCollectorOptions - extends CollectorOptions<[T, Collection]> { +export interface InteractionCollectorOptions< + Interaction extends CollectedInteraction, + Cached extends CacheType = CacheType, +> extends CollectorOptions<[Interaction, Collection]> { channel?: TextBasedChannelResolvable; componentType?: ComponentType; guild?: GuildResolvable; @@ -5900,9 +5955,9 @@ export interface InviteCreateOptions { export type InviteResolvable = string; -export interface LifetimeFilterOptions { - excludeFromSweep?: (value: V, key: K, collection: LimitedCollection) => boolean; - getComparisonTimestamp?: (value: V, key: K, collection: LimitedCollection) => number; +export interface LifetimeFilterOptions { + excludeFromSweep?: (value: Value, key: Key, collection: LimitedCollection) => boolean; + getComparisonTimestamp?: (value: Value, key: Key, collection: LimitedCollection) => number; lifetime?: number; } @@ -5967,13 +6022,13 @@ export type CollectedMessageInteraction = ModalSubmitInteraction >; -export type MessageComponentCollectorOptions = Omit< - InteractionCollectorOptions, +export type MessageComponentCollectorOptions = Omit< + InteractionCollectorOptions, 'channel' | 'message' | 'guild' | 'interactionType' >; -export type MessageChannelComponentCollectorOptions = Omit< - InteractionCollectorOptions, +export type MessageChannelComponentCollectorOptions = Omit< + InteractionCollectorOptions, 'channel' | 'guild' | 'interactionType' >; @@ -6157,9 +6212,9 @@ export type PermissionResolvable = BitFieldResolvable = ReadonlyArray>; +export type RecursiveArray = ReadonlyArray>; -export type RecursiveReadonlyArray = ReadonlyArray>; +export type RecursiveReadonlyArray = ReadonlyArray>; export interface PartialRecipient { username: string; @@ -6200,18 +6255,18 @@ export interface PartialEmojiOnlyId { } export type Partialize< - T extends AllowedPartial, - NulledKeys extends keyof T | null = null, - NullableKeys extends keyof T | null = null, - OverridableKeys extends keyof T | '' = '', + PartialType extends AllowedPartial, + NulledKeys extends keyof PartialType | null = null, + NullableKeys extends keyof PartialType | null = null, + OverridableKeys extends keyof PartialType | '' = '', > = { - [K in keyof Omit]: K extends 'partial' + [K in keyof Omit]: K extends 'partial' ? true : K extends NulledKeys ? null : K extends NullableKeys - ? T[K] | null - : T[K]; + ? PartialType[K] | null + : PartialType[K]; }; export interface PartialDMChannel extends Partialize { @@ -6373,11 +6428,11 @@ export interface SupportingInteractionResolvedData { export type SweeperKey = keyof SweeperDefinitions; -export type CollectionSweepFilter = (value: V, key: K, collection: Collection) => boolean; +export type CollectionSweepFilter = (value: Value, key: Key, collection: Collection) => boolean; -export interface SweepOptions { +export interface SweepOptions { interval: number; - filter: GlobalSweepFilter; + filter: GlobalSweepFilter; } export interface LifetimeSweepOptions { @@ -6405,14 +6460,14 @@ export interface SweeperDefinitions { } export type SweeperOptions = { - [K in keyof SweeperDefinitions]?: SweeperDefinitions[K][2] extends true - ? SweepOptions | LifetimeSweepOptions - : SweepOptions; + [Key in keyof SweeperDefinitions]?: SweeperDefinitions[Key][2] extends true + ? SweepOptions | LifetimeSweepOptions + : SweepOptions; }; -export interface LimitedCollectionOptions { +export interface LimitedCollectionOptions { maxSize?: number; - keepOverLimit?: (value: V, key: K, collection: LimitedCollection) => boolean; + keepOverLimit?: (value: Value, key: Key, collection: LimitedCollection) => boolean; } export type Channel = @@ -6588,17 +6643,17 @@ export interface ClientApplicationInstallParams { permissions: Readonly; } -export type Serialized = T extends symbol | bigint | (() => any) +export type Serialized = Value extends symbol | bigint | (() => any) ? never - : T extends number | string | boolean | undefined - ? T - : T extends { toJSON(): infer R } - ? R - : T extends ReadonlyArray - ? Serialized[] - : T extends ReadonlyMap | ReadonlySet + : Value extends number | string | boolean | undefined + ? Value + : Value extends { toJSON(): infer JSONResult } + ? JSONResult + : Value extends ReadonlyArray + ? Serialized[] + : Value extends ReadonlyMap | ReadonlySet ? {} - : { [K in keyof T]: Serialized }; + : { [K in keyof Value]: Serialized }; //#endregion diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index 09716af8d9ad..f07e3e8b68ef 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -190,8 +190,11 @@ import { expectAssignable, expectNotAssignable, expectNotType, expectType } from import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders'; // Test type transformation: -declare const serialize: (value: T) => Serialized; -declare const notPropertyOf: (value: T, property: P & Exclude) => void; +declare const serialize: (value: Value) => Serialized; +declare const notPropertyOf: ( + value: Value, + property: Property & Exclude, +) => void; const client: Client = new Client({ intents: GatewayIntentBits.Guilds, diff --git a/packages/docgen/src/types/item.ts b/packages/docgen/src/types/item.ts index 9c56b009c8bc..b58fe83c5c0d 100644 --- a/packages/docgen/src/types/item.ts +++ b/packages/docgen/src/types/item.ts @@ -1,9 +1,9 @@ import type { DeclarationReflection } from 'typedoc'; import type { Config, Item } from '../interfaces/index.js'; -export class DocumentedItem { +export class DocumentedItem { public constructor( - public readonly data: T, + public readonly data: Data, public readonly config: Config, ) {} diff --git a/packages/formatters/src/formatters.ts b/packages/formatters/src/formatters.ts index 5e84e0d9ef2e..3a31e306fdf2 100644 --- a/packages/formatters/src/formatters.ts +++ b/packages/formatters/src/formatters.ts @@ -4,20 +4,23 @@ import type { Snowflake } from 'discord-api-types/globals'; /** * Wraps the content inside a code block with no language. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function codeBlock(content: C): `\`\`\`\n${C}\n\`\`\``; +export function codeBlock(content: Content): `\`\`\`\n${Content}\n\`\`\``; /** * Wraps the content inside a code block with the specified language. * - * @typeParam L - This is inferred by the supplied language - * @typeParam C - This is inferred by the supplied content + * @typeParam Language - This is inferred by the supplied language + * @typeParam Content - This is inferred by the supplied content * @param language - The language for the code block * @param content - The content to wrap */ -export function codeBlock(language: L, content: C): `\`\`\`${L}\n${C}\n\`\`\``; +export function codeBlock( + language: Language, + content: Content, +): `\`\`\`${Language}\n${Content}\n\`\`\``; export function codeBlock(language: string, content?: string): string { return content === undefined ? `\`\`\`\n${language}\n\`\`\`` : `\`\`\`${language}\n${content}\n\`\`\``; @@ -26,50 +29,50 @@ export function codeBlock(language: string, content?: string): string { /** * Wraps the content inside \`backticks\` which formats it as inline code. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function inlineCode(content: C): `\`${C}\`` { +export function inlineCode(content: Content): `\`${Content}\`` { return `\`${content}\``; } /** * Formats the content into italic text. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function italic(content: C): `_${C}_` { +export function italic(content: Content): `_${Content}_` { return `_${content}_`; } /** * Formats the content into bold text. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function bold(content: C): `**${C}**` { +export function bold(content: Content): `**${Content}**` { return `**${content}**`; } /** * Formats the content into underscored text. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function underscore(content: C): `__${C}__` { +export function underscore(content: Content): `__${Content}__` { return `__${content}__`; } /** * Formats the content into strike-through text. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function strikethrough(content: C): `~~${C}~~` { +export function strikethrough(content: Content): `~~${Content}~~` { return `~~${content}~~`; } @@ -77,10 +80,10 @@ export function strikethrough(content: C): `~~${C}~~` { * Formats the content into a quote. * * @remarks This needs to be at the start of the line for Discord to format it. - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function quote(content: C): `> ${C}` { +export function quote(content: Content): `> ${Content}` { return `> ${content}`; } @@ -88,20 +91,20 @@ export function quote(content: C): `> ${C}` { * Formats the content into a block quote. * * @remarks This needs to be at the start of the line for Discord to format it. - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function blockQuote(content: C): `>>> ${C}` { +export function blockQuote(content: Content): `>>> ${Content}` { return `>>> ${content}`; } /** * Wraps the URL into `<>` which stops it from embedding. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param url - The URL to wrap */ -export function hideLinkEmbed(url: C): `<${C}>`; +export function hideLinkEmbed(url: Content): `<${Content}>`; /** * Wraps the URL into `<>` which stops it from embedding. @@ -117,52 +120,55 @@ export function hideLinkEmbed(url: URL | string) { /** * Formats the content and the URL into a masked URL. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to display * @param url - The URL the content links to */ -export function hyperlink(content: C, url: URL): `[${C}](${string})`; +export function hyperlink(content: Content, url: URL): `[${Content}](${string})`; /** * Formats the content and the URL into a masked URL. * - * @typeParam C - This is inferred by the supplied content - * @typeParam U - This is inferred by the supplied URL + * @typeParam Content - This is inferred by the supplied content + * @typeParam Url - This is inferred by the supplied URL * @param content - The content to display * @param url - The URL the content links to */ -export function hyperlink(content: C, url: U): `[${C}](${U})`; +export function hyperlink( + content: Content, + url: Url, +): `[${Content}](${Url})`; /** * Formats the content and the URL into a masked URL with a custom tooltip. * - * @typeParam C - This is inferred by the supplied content - * @typeParam T - This is inferred by the supplied title + * @typeParam Content - This is inferred by the supplied content + * @typeParam Title - This is inferred by the supplied title * @param content - The content to display * @param url - The URL the content links to * @param title - The title shown when hovering on the masked link */ -export function hyperlink( - content: C, +export function hyperlink( + content: Content, url: URL, - title: T, -): `[${C}](${string} "${T}")`; + title: Title, +): `[${Content}](${string} "${Title}")`; /** * Formats the content and the URL into a masked URL with a custom tooltip. * - * @typeParam C - This is inferred by the supplied content - * @typeParam U - This is inferred by the supplied URL - * @typeParam T - This is inferred by the supplied title + * @typeParam Content - This is inferred by the supplied content + * @typeParam Url - This is inferred by the supplied URL + * @typeParam Title - This is inferred by the supplied title * @param content - The content to display * @param url - The URL the content links to * @param title - The title shown when hovering on the masked link */ -export function hyperlink( - content: C, - url: U, - title: T, -): `[${C}](${U} "${T}")`; +export function hyperlink( + content: Content, + url: Url, + title: Title, +): `[${Content}](${Url} "${Title}")`; export function hyperlink(content: string, url: URL | string, title?: string) { return title ? `[${content}](${url} "${title}")` : `[${content}](${url})`; @@ -171,102 +177,114 @@ export function hyperlink(content: string, url: URL | string, title?: string) { /** * Formats the content into a spoiler. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap */ -export function spoiler(content: C): `||${C}||` { +export function spoiler(content: Content): `||${Content}||` { return `||${content}||`; } /** * Formats a user id into a user mention. * - * @typeParam C - This is inferred by the supplied user id + * @typeParam UserId - This is inferred by the supplied user id * @param userId - The user id to format */ -export function userMention(userId: C): `<@${C}>` { +export function userMention(userId: UserId): `<@${UserId}>` { return `<@${userId}>`; } /** * Formats a channel id into a channel mention. * - * @typeParam C - This is inferred by the supplied channel id + * @typeParam ChannelId - This is inferred by the supplied channel id * @param channelId - The channel id to format */ -export function channelMention(channelId: C): `<#${C}>` { +export function channelMention(channelId: ChannelId): `<#${ChannelId}>` { return `<#${channelId}>`; } /** * Formats a role id into a role mention. * - * @typeParam C - This is inferred by the supplied role id + * @typeParam RoleId - This is inferred by the supplied role id * @param roleId - The role id to format */ -export function roleMention(roleId: C): `<@&${C}>` { +export function roleMention(roleId: RoleId): `<@&${RoleId}>` { return `<@&${roleId}>`; } /** * Formats an application command name, subcommand group name, subcommand name, and id into an application command mention. * - * @typeParam N - This is inferred by the supplied command name - * @typeParam G - This is inferred by the supplied subcommand group name - * @typeParam S - This is inferred by the supplied subcommand name - * @typeParam I - This is inferred by the supplied command id + * @typeParam CommandName - This is inferred by the supplied command name + * @typeParam SubcommandGroupName - This is inferred by the supplied subcommand group name + * @typeParam SubcommandName - This is inferred by the supplied subcommand name + * @typeParam CommandId - This is inferred by the supplied command id * @param commandName - The application command name to format * @param subcommandGroupName - The subcommand group name to format * @param subcommandName - The subcommand name to format * @param commandId - The application command id to format */ export function chatInputApplicationCommandMention< - N extends string, - G extends string, - S extends string, - I extends Snowflake, ->(commandName: N, subcommandGroupName: G, subcommandName: S, commandId: I): ``; + CommandName extends string, + SubcommandGroupName extends string, + SubcommandName extends string, + CommandId extends Snowflake, +>( + commandName: CommandName, + subcommandGroupName: SubcommandGroupName, + subcommandName: SubcommandName, + commandId: CommandId, +): ``; /** * Formats an application command name, subcommand name, and id into an application command mention. * - * @typeParam N - This is inferred by the supplied command name - * @typeParam S - This is inferred by the supplied subcommand name - * @typeParam I - This is inferred by the supplied command id + * @typeParam CommandName - This is inferred by the supplied command name + * @typeParam SubcommandName - This is inferred by the supplied subcommand name + * @typeParam CommandId - This is inferred by the supplied command id * @param commandName - The application command name to format * @param subcommandName - The subcommand name to format * @param commandId - The application command id to format */ -export function chatInputApplicationCommandMention( - commandName: N, - subcommandName: S, - commandId: I, -): ``; +export function chatInputApplicationCommandMention< + CommandName extends string, + SubcommandName extends string, + CommandId extends Snowflake, +>( + commandName: CommandName, + subcommandName: SubcommandName, + commandId: CommandId, +): ``; /** * Formats an application command name and id into an application command mention. * - * @typeParam N - This is inferred by the supplied command name - * @typeParam I - This is inferred by the supplied command id + * @typeParam CommandName - This is inferred by the supplied command name + * @typeParam CommandId - This is inferred by the supplied command id * @param commandName - The application command name to format * @param commandId - The application command id to format */ -export function chatInputApplicationCommandMention( - commandName: N, - commandId: I, -): ``; +export function chatInputApplicationCommandMention( + commandName: CommandName, + commandId: CommandId, +): ``; export function chatInputApplicationCommandMention< - N extends string, - G extends Snowflake | string, - S extends Snowflake | string, - I extends Snowflake, + CommandName extends string, + SubcommandGroupName extends Snowflake | string, + SubcommandName extends Snowflake | string, + CommandId extends Snowflake, >( - commandName: N, - subcommandGroupName: G, - subcommandName?: S, - commandId?: I, -): `` | `` | `` { + commandName: CommandName, + subcommandGroupName: SubcommandGroupName, + subcommandName?: SubcommandName, + commandId?: CommandId, +): + | `` + | `` + | `` { if (commandId !== undefined) { return ``; } @@ -281,95 +299,105 @@ export function chatInputApplicationCommandMention< /** * Formats a non-animated emoji id into a fully qualified emoji identifier. * - * @typeParam C - This is inferred by the supplied emoji id + * @typeParam EmojiId - This is inferred by the supplied emoji id * @param emojiId - The emoji id to format */ -export function formatEmoji(emojiId: C, animated?: false): `<:_:${C}>`; +export function formatEmoji(emojiId: EmojiId, animated?: false): `<:_:${EmojiId}>`; /** * Formats an animated emoji id into a fully qualified emoji identifier. * - * @typeParam C - This is inferred by the supplied emoji id + * @typeParam EmojiId - This is inferred by the supplied emoji id * @param emojiId - The emoji id to format * @param animated - Whether the emoji is animated */ -export function formatEmoji(emojiId: C, animated?: true): ``; +export function formatEmoji(emojiId: EmojiId, animated?: true): ``; /** * Formats an emoji id into a fully qualified emoji identifier. * - * @typeParam C - This is inferred by the supplied emoji id + * @typeParam EmojiId - This is inferred by the supplied emoji id * @param emojiId - The emoji id to format * @param animated - Whether the emoji is animated */ -export function formatEmoji(emojiId: C, animated?: boolean): `<:_:${C}>` | ``; +export function formatEmoji( + emojiId: EmojiId, + animated?: boolean, +): `<:_:${EmojiId}>` | ``; -export function formatEmoji(emojiId: C, animated = false): `<:_:${C}>` | `` { +export function formatEmoji( + emojiId: EmojiId, + animated = false, +): `<:_:${EmojiId}>` | `` { return `<${animated ? 'a' : ''}:_:${emojiId}>`; } /** * Formats a channel link for a direct message channel. * - * @typeParam C - This is inferred by the supplied channel id + * @typeParam ChannelId - This is inferred by the supplied channel id * @param channelId - The channel's id */ -export function channelLink(channelId: C): `https://discord.com/channels/@me/${C}`; +export function channelLink( + channelId: ChannelId, +): `https://discord.com/channels/@me/${ChannelId}`; /** * Formats a channel link for a guild channel. * - * @typeParam C - This is inferred by the supplied channel id - * @typeParam G - This is inferred by the supplied guild id + * @typeParam ChannelId - This is inferred by the supplied channel id + * @typeParam GuildId - This is inferred by the supplied guild id * @param channelId - The channel's id * @param guildId - The guild's id */ -export function channelLink( - channelId: C, - guildId: G, -): `https://discord.com/channels/${G}/${C}`; +export function channelLink( + channelId: ChannelId, + guildId: GuildId, +): `https://discord.com/channels/${GuildId}/${ChannelId}`; -export function channelLink( - channelId: C, - guildId?: G, -): `https://discord.com/channels/@me/${C}` | `https://discord.com/channels/${G}/${C}` { +export function channelLink( + channelId: ChannelId, + guildId?: GuildId, +): `https://discord.com/channels/@me/${ChannelId}` | `https://discord.com/channels/${GuildId}/${ChannelId}` { return `https://discord.com/channels/${guildId ?? '@me'}/${channelId}`; } /** * Formats a message link for a direct message channel. * - * @typeParam C - This is inferred by the supplied channel id - * @typeParam M - This is inferred by the supplied message id + * @typeParam ChannelId - This is inferred by the supplied channel id + * @typeParam MessageId - This is inferred by the supplied message id * @param channelId - The channel's id * @param messageId - The message's id */ -export function messageLink( - channelId: C, - messageId: M, -): `https://discord.com/channels/@me/${C}/${M}`; +export function messageLink( + channelId: ChannelId, + messageId: MessageId, +): `https://discord.com/channels/@me/${ChannelId}/${MessageId}`; /** * Formats a message link for a guild channel. * - * @typeParam C - This is inferred by the supplied channel id - * @typeParam M - This is inferred by the supplied message id - * @typeParam G - This is inferred by the supplied guild id + * @typeParam ChannelId - This is inferred by the supplied channel id + * @typeParam MessageId - This is inferred by the supplied message id + * @typeParam GuildId - This is inferred by the supplied guild id * @param channelId - The channel's id * @param messageId - The message's id * @param guildId - The guild's id */ -export function messageLink( - channelId: C, - messageId: M, - guildId: G, -): `https://discord.com/channels/${G}/${C}/${M}`; - -export function messageLink( - channelId: C, - messageId: M, - guildId?: G, -): `https://discord.com/channels/@me/${C}/${M}` | `https://discord.com/channels/${G}/${C}/${M}` { +export function messageLink( + channelId: ChannelId, + messageId: MessageId, + guildId: GuildId, +): `https://discord.com/channels/${GuildId}/${ChannelId}/${MessageId}`; + +export function messageLink( + channelId: ChannelId, + messageId: MessageId, + guildId?: GuildId, +): + | `https://discord.com/channels/@me/${ChannelId}/${MessageId}` + | `https://discord.com/channels/${GuildId}/${ChannelId}/${MessageId}` { return `${guildId === undefined ? channelLink(channelId) : channelLink(channelId, guildId)}/${messageId}`; } @@ -394,29 +422,29 @@ export enum HeadingLevel { /** * Formats the content into a heading level. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap * @param level - The heading level */ -export function heading(content: C, level?: HeadingLevel.One): `# ${C}`; +export function heading(content: Content, level?: HeadingLevel.One): `# ${Content}`; /** * Formats the content into a heading level. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap * @param level - The heading level */ -export function heading(content: C, level: HeadingLevel.Two): `## ${C}`; +export function heading(content: Content, level: HeadingLevel.Two): `## ${Content}`; /** * Formats the content into a heading level. * - * @typeParam C - This is inferred by the supplied content + * @typeParam Content - This is inferred by the supplied content * @param content - The content to wrap * @param level - The heading level */ -export function heading(content: C, level: HeadingLevel.Three): `### ${C}`; +export function heading(content: Content, level: HeadingLevel.Three): `### ${Content}`; export function heading(content: string, level?: HeadingLevel) { switch (level) { @@ -432,7 +460,7 @@ export function heading(content: string, level?: HeadingLevel) { /** * A type that recursively traverses into arrays. */ -export type RecursiveArray = readonly (RecursiveArray | T)[]; +export type RecursiveArray = readonly (ItemType | RecursiveArray)[]; /** * Callback function for list formatters. @@ -476,29 +504,32 @@ export function time(date?: Date): ``; /** * Formats a date given a format style. * - * @typeParam S - This is inferred by the supplied {@link TimestampStylesString} + * @typeParam Style - This is inferred by the supplied {@link TimestampStylesString} * @param date - The date to format * @param style - The style to use */ -export function time(date: Date, style: S): ``; +export function time