From b39860ef8da40241be2681d733cb1fdcd2feb164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20LES=C3=89N=C3=89CHAL?= Date: Mon, 29 Jan 2024 18:55:05 +0100 Subject: [PATCH] Simplify types to avoid duplicates (and for clarity), by using additional types and interfaces --- jquery/client.d.ts | 22 +++++++++--------- mw/Api.d.ts | 58 +++++++++++++++++++++++++++------------------- mw/Uri.d.ts | 11 +++++---- mw/index.d.ts | 34 ++++++++++++++++++--------- mw/user.d.ts | 12 ++++++---- mw/util.d.ts | 42 +++++++++++++++++++-------------- 6 files changed, 105 insertions(+), 74 deletions(-) diff --git a/jquery/client.d.ts b/jquery/client.d.ts index 20c6dc6..152e6e6 100644 --- a/jquery/client.d.ts +++ b/jquery/client.d.ts @@ -119,18 +119,14 @@ interface Client { * } * ``` * - * @param {Object} map Browser support map + * @param {ClientSupportMap} map Browser support map * @param {ClientProfile} [profile] A client-profile object * @param {boolean} [exactMatchOnly=false] Only return true if the browser is matched, * otherwise returns true if the browser is not found. * @returns {boolean} The current browser is in the support map * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/jQuery.client-method-test */ - test( - map: ClientSupportMap | { ltr: ClientSupportMap; rtl: ClientSupportMap }, - profile?: ClientProfile, - exactMatchOnly?: boolean - ): boolean; + test(map: ClientSupportMap, profile?: ClientProfile, exactMatchOnly?: boolean): boolean; } export interface ClientNavigator { @@ -152,11 +148,15 @@ type ClientProfileName = | "safari" | "silk"; -type ClientSupportMap = Partial>; -type ClientSupportCondition = [ - "==" | "===" | "!=" | "!==" | "<" | "<=" | ">" | ">=", - string | number -]; +type ComparisonOperator = "==" | "===" | "!=" | "!==" | "<" | "<=" | ">" | ">="; +type ClientSupportCondition = [ComparisonOperator, string | number]; + +type UndirectedClientSupportMap = Partial< + Record +>; +type ClientSupportMap = + | UndirectedClientSupportMap + | Record<"ltr" | "rtl", UndirectedClientSupportMap>; interface ClientProfile { name: ClientProfileName; diff --git a/mw/Api.d.ts b/mw/Api.d.ts index 416d9e6..10bc406 100644 --- a/mw/Api.d.ts +++ b/mw/Api.d.ts @@ -14,6 +14,28 @@ type ReplaceValue = T extends U[] ? V[] : V; type ApiParams = Record; type ApiResponse = Record; // it will always be a JSON object, the rest is uncertain ... +interface Revision { + content: string; + timestamp: string; +} + +interface AssertUser { + assert: "anon" | "user"; + assertUser: string; +} + +interface WatchStatus { + title: string; + watched: boolean; +} + +interface FinishUpload { + /** + * Call this function to finish the upload. + */ + (data?: ApiUploadParams): JQuery.Promise; +} + /** * Default options for {@link jQuery.ajax} calls. Can be overridden by passing * `options` to {@link mw.Api} constructor. @@ -319,16 +341,13 @@ declare global { * ``` * * @param {TitleLike} title Page title - * @param {function({ timestamp: string, content: string }):string|ApiEditPageParams} transform Callback that prepares the edit + * @param {function(Revision):string|ApiEditPageParams} transform Callback that prepares the edit * @returns {JQuery.Promise} * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api.plugin.edit-method-edit */ edit( title: TitleLike, - transform: (data: { - timestamp: string; - content: string; - }) => string | ApiEditPageParams + transform: (revision: Revision) => string | ApiEditPageParams ): JQuery.Promise; /** @@ -367,15 +386,10 @@ declare global { * * `apierror-assertnameduserfailed`: when both the client-side logic and the server thinks the user is logged in but they see it logged in under a different username. * * @param {ApiParams} query Query parameters. The object will not be changed - * @returns {JQuery.Promise<{ assert: "anon" | "user", assertUser: string }>} + * @returns {JQuery.Promise} * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api.plugin.user-method-assertCurrentUser */ - assertCurrentUser( - query: ApiParams - ): JQuery.Promise<{ - assert: "anon" | "user"; - assertUser: string; - }>; + assertCurrentUser(query: ApiParams): JQuery.Promise; /** * Asynchronously save the value of a single user option using the API. See `saveOptions()`. @@ -409,29 +423,25 @@ declare global { * * @param {TypeOrArray} pages * @param {string} [expiry] - * @returns {JQuery.Promise<{ watch: TypeOrArray<{ title: string, watched: boolean }> }>} + * @returns {JQuery.Promise<{ watch: TypeOrArray }>} * @since 1.35: expiry parameter can be passed when watchlist expiry is enabled * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api.plugin.watch-method-watch */ watch

>( pages: P, expiry?: string - ): JQuery.Promise<{ - watch: ReplaceValue; - }>; + ): JQuery.Promise<{ watch: ReplaceValue }>; /** * Convenience method for `action=watch&unwatch=1`. * * @param {TypeOrArray} pages - * @returns {JQuery.Promise<{ watch: TypeOrArray<{ title: string, watched: boolean }> }>} + * @returns {JQuery.Promise<{ watch: TypeOrArray }>} * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api.plugin.watch-method-unwatch */ unwatch

>( pages: P - ): JQuery.Promise<{ - watch: ReplaceValue; - }>; + ): JQuery.Promise<{ watch: ReplaceValue }>; /** * Convenience method for `action=parse`. @@ -553,7 +563,7 @@ declare global { * @param {ApiUploadParams} [data] * @param {number} [chunkSize] Size (in bytes) per chunk (default: 5MB) * @param {number} [chunkRetries] Amount of times to retry a failed chunk (default: 1) - * @returns {JQuery.Promise<(data?: ApiUploadParams) => JQuery.Promise>} Call this function to finish the upload + * @returns {JQuery.Promise} * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api.plugin.upload-method-chunkedUploadToStash */ chunkedUploadToStash( @@ -561,7 +571,7 @@ declare global { data?: ApiUploadParams, chunkSize?: number, chunkRetries?: number - ): JQuery.Promise<(data?: ApiUploadParams) => JQuery.Promise>; + ): JQuery.Promise; /** * Upload a file to MediaWiki. @@ -606,13 +616,13 @@ declare global { * * @param {File|HTMLInputElement} file * @param {ApiUploadParams} [data] - * @returns {JQuery.Promise<(data?: ApiUploadParams) => JQuery.Promise>} Call this function to finish the upload + * @returns {JQuery.Promise} * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api.plugin.upload-method-uploadToStash */ uploadToStash( file: File | HTMLInputElement, data?: ApiUploadParams - ): JQuery.Promise<(data?: ApiUploadParams) => JQuery.Promise>; + ): JQuery.Promise; /** * @param {string} username diff --git a/mw/Uri.d.ts b/mw/Uri.d.ts index 09d786f..52213d0 100644 --- a/mw/Uri.d.ts +++ b/mw/Uri.d.ts @@ -17,6 +17,11 @@ interface UriOptions { arrayParams: boolean; } +interface UriParser { + strict: RegExp; + loose: RegExp; +} + declare global { namespace mw { /** @@ -134,13 +139,9 @@ declare global { * file where they make use of named capture groups. That syntax isn't valid in JavaScript ES5, * so the server-side strips these before delivering to the client. * - * @property {Object} parser * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Uri-static-property-parser */ - private static parser: { - strict: RegExp; - loose: RegExp; - }; + private static parser: UriParser; /** * The order here matches the order of captured matches in the `parser` property regexes. diff --git a/mw/index.d.ts b/mw/index.d.ts index 31d5e0c..27de9fb 100644 --- a/mw/index.d.ts +++ b/mw/index.d.ts @@ -21,6 +21,24 @@ import "./Uri"; import "./user"; import "./util"; +type ObjectAnalyticEventData = Record; +type AnalyticEventData = ObjectAnalyticEventData | number | string | undefined; + +interface ErrorAnalyticEventData extends ObjectAnalyticEventData { + exception?: any; + module?: string; + source: string; +} + +interface AnalyticEvent { + topic: string; + data: AnalyticEventData; +} + +interface AnalyticEventCallback { + (topic: string, data: AnalyticEventData): void; +} + declare global { /** * Base library for MediaWiki. @@ -128,7 +146,7 @@ declare global { * @param {Object|number|string} [data] Data describing the event. * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw-method-track */ - function track(topic: string, data?: object | number | string): void; + function track(topic: string, data?: AnalyticEventData): void; /** * Track an early error event via mw.track and send it to the window console. @@ -138,7 +156,7 @@ declare global { * @param {Object} data Data describing the event, encoded as an object; see {@link errorLogger.logError} * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw-method-trackError */ - function trackError(topic: string, data: object): void; + function trackError(topic: string, data: ErrorAnalyticEventData): void; /** * Register a handler for subset of analytic events, specified by topic. @@ -165,17 +183,14 @@ declare global { * @param {string} callback.topic * @param {Object} [callback.data] */ - function trackSubscribe( - topic: string, - callback: (topic: string, data: object) => void - ): void; + function trackSubscribe(topic: string, callback: AnalyticEventCallback): void; /** * Stop handling events for a particular handler * * @param {Function} callback */ - function trackUnsubscribe(callback: (topic: string, data: object) => void): void; + function trackUnsubscribe(callback: AnalyticEventCallback): void; /** * List of all analytic events emitted so far. @@ -185,10 +200,7 @@ declare global { * @private * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw-property-trackQueue */ - const trackQueue: Array<{ - topic: string; - data: Record | number | string | undefined; - }>; + const trackQueue: AnalyticEvent[]; } } diff --git a/mw/user.d.ts b/mw/user.d.ts index 7dc3474..c09499c 100644 --- a/mw/user.d.ts +++ b/mw/user.d.ts @@ -9,6 +9,12 @@ export interface UserInfo { rights: string[]; } +interface UserTokens extends Record { + csrfToken: string; + patrolToken: string; + watchToken: string; +} + export interface User { /** * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.user-property-options @@ -19,11 +25,7 @@ export interface User { /** * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.user-property-tokens */ - tokens: mw.Map<{ - csrfToken: string; - patrolToken: string; - watchToken: string; - }>; + tokens: mw.Map; /** * Acquire a temporary user username and stash it in the current session, if temp account creation diff --git a/mw/util.d.ts b/mw/util.d.ts index a68efb7..922377e 100644 --- a/mw/util.d.ts +++ b/mw/util.d.ts @@ -9,6 +9,28 @@ type NoReturn any> = T extends ( : (this: U, ...args: V) => void : never; +interface ImageUrlData { + /** + * File name (same format as {@link mw.Title.getMainText()}). + */ + name: string; + + /** + * Thumbnail width, in pixels. Null when the file is not a thumbnail. + */ + width: number | null; + + /** + * @param w Width, which must be smaller than the width of the original image (or equal to it; that + * only works if `MediaHandler::mustRender` returns true for the file). Null when the + * file in the original URL is not a thumbnail. + * On wikis with `$wgGenerateThumbnailOnParse` set to true, this will fall back to using + * `Special:Redirect` which is less efficient. Otherwise, it is a direct thumbnail URL. + * @returns A thumbnail URL (URL-encoded) with that width. + */ + resizeUrl: (w: number) => string | null; +} + declare global { namespace mw { /** @@ -403,27 +425,11 @@ declare global { * the image. * * @param {string} url URL to parse (URL-encoded) - * @returns {Object|null} URL data, or null if the URL is not a valid MediaWiki + * @returns {ImageUrlData|null} URL data, or null if the URL is not a valid MediaWiki * image/thumbnail URL. - * @returns {string} return.name File name (same format as Title.getMainText()). - * @returns {number} [return.width] Thumbnail width, in pixels. Null when the file is not - * a thumbnail. - * @returns {function(number):string} [return.resizeUrl] A function that takes a width - * parameter and returns a thumbnail URL (URL-encoded) with that width. The width - * parameter must be smaller than the width of the original image (or equal to it; that - * only works if MediaHandler::mustRender returns true for the file). Null when the - * file in the original URL is not a thumbnail. - * On wikis with $wgGenerateThumbnailOnParse set to true, this will fall back to using - * Special:Redirect which is less efficient. Otherwise, it is a direct thumbnail URL. * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.util-method-parseImageUrl */ - function parseImageUrl( - url: string - ): { - name: string; - width?: number | null; - resizeUrl(w: number): string; - } | null; + function parseImageUrl(url: string): ImageUrlData | null; /** * Percent-decode a string, as found in a URL hash fragment