Skip to content

Commit

Permalink
refactor(mw.Map): improve autocompletion
Browse files Browse the repository at this point in the history
check other authors/commits at wikimedia-gadgets#36
  • Loading branch information
AnYiEE committed Feb 16, 2024
1 parent fd351c9 commit 9d83f84
Showing 1 changed file with 64 additions and 7 deletions.
71 changes: 64 additions & 7 deletions mw/Map.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,64 @@
type KeyOrArray<T> = keyof T | Array<keyof T>;
type GetOrDefault<V, K extends keyof V, T> = V extends Required<Pick<V, K>> ? V[K] : Required<V>[K] | T;
type PickOrDefault<V, S extends keyof V | Array<keyof V>, T> =
S extends Array<infer SS> ? {[K in SS & keyof V]-?: GetOrDefault<V, K, T>} : GetOrDefault<V, S & keyof V, null>;
type TypeOrArray<T> = T | T[];

// Get/PickOrDefault<V, S, TD, TX> extracts values from V using key selection S
// - TD is the value type of missing properties
// - TX is the value type of unknown properties

type GetOrDefault<V, K extends PropertyKey, TD, TX = unknown> = K extends keyof V
? V extends Required<Pick<V, K>>
? V[K]
: Required<V>[K] | TD
: TX | TD;

type PickOrDefault<V, S extends TypeOrArray<PropertyKey>, TD, TX = unknown> =
S extends Array<infer K>
? {[P in K & PropertyKey]-?: GetOrDefault<V, P, TD, TX>}
: GetOrDefault<V, S & PropertyKey, TD, TX>;

// `ExtensibleMap<V, TX>` is an alternative to `Map<V & { [k: string]: TX; }>`
// but unlike the latter, ExtensibleMap provides additional overloads to improve selection
// autocompletion and type checking.

export interface ExtensibleMap<V extends Record<string, any>, TX = unknown> extends mw.Map<V> {
/**
* Check if a given key exists in the map.
*
* @param selection Key to check
* @returns True if the key exists
* @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-exists
*/
exists<S extends keyof V>(selection: S): selection is S;
exists<S extends string>(selection: S): selection is S;

/**
* Get the value of one or more keys.
*
* If called with no arguments, all values are returned.
*
* @param selection Key or array of keys to retrieve values for.
* @param fallback Value for keys that don't exist.
* @returns If selection was a string, returns the value. If selection was an array, returns
* an object of key/values. If no selection is passed, a new object with all key/values is returned.
* @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-get
*/
get<S extends TypeOrArray<keyof V>, TD>(selection: S, fallback: TD): PickOrDefault<V, S, TD, TX>;
get<S extends TypeOrArray<string>, TD>(selection: S, fallback: TD): PickOrDefault<V, S, TD, TX>;
get<S extends TypeOrArray<keyof V>>(selection: S): PickOrDefault<V, S, null, TX>;
get<S extends TypeOrArray<string>>(selection: S): PickOrDefault<V, S, null, TX>;
get<T extends Record<string, any> = V | Record<string, TX>>(): T;

/**
* Set the value of one or more keys.
*
* @param selection Key to set value for, or object mapping keys to values
* @param value Value to set (optional, only in use when key is a string)
* @returns True on success, false on failure
* @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-set
*/
set<S extends keyof V>(selection: S, value: V[S]): boolean;
set<S extends string>(selection: S, value: TX): boolean;
set<S extends Partial<V> & Record<string, TX>>(selection: S): boolean;
}

declare global {
namespace mw {
Expand Down Expand Up @@ -40,9 +97,9 @@ declare global {
* an object of key/values. If no selection is passed, a new object with all key/values is returned.
* @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-get
*/
get<S extends KeyOrArray<V>, T>(selection: S, fallback: T): PickOrDefault<V, S, T>;
get<S extends KeyOrArray<V>>(selection: S): PickOrDefault<V, S, null>;
get<S extends V>(): S;
get<S extends TypeOrArray<keyof V>, TD>(selection: S, fallback: TD): PickOrDefault<V, S, TD>;
get<S extends TypeOrArray<keyof V>>(selection: S): PickOrDefault<V, S, null>;
get<T extends V = V>(): T;

/**
* Set the value of one or more keys.
Expand Down

0 comments on commit 9d83f84

Please sign in to comment.