How to understand the String.prototype.replace TypeScript definition?

Viewed 88

I found type definition of String.prototype.replace in lib.es2015.symbol.wellknown.d.ts by cmd+click on someString.replace:

interface String {
    /**
     * Matches a string or an object that supports being matched against, and returns an array
     * containing the results of that search, or null if no matches are found.
     * @param matcher An object that supports being matched against.
     */
    match(matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null;

    /**
     * Replaces text in a string, using an object that supports replacement within a string.
     * @param searchValue A object can search for and replace matches within a string.
     * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
     */
    replace(searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, replaceValue: string): string;

    /**
     * Replaces text in a string, using an object that supports replacement within a string.
     * @param searchValue A object can search for and replace matches within a string.
     * @param replacer A function that returns the replacement text.
     */
    replace(searchValue: { [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; }, replacer: (substring: string, ...args: any[]) => string): string;

    /**
     * Finds the first substring match in a regular expression search.
     * @param searcher An object which supports searching within a string.
     */
    search(searcher: { [Symbol.search](string: string): number; }): number;

    /**
     * Split a string into substrings using the specified separator and return them as an array.
     * @param splitter An object that can split a string.
     * @param limit A value used to limit the number of elements returned in the array.
     */
    split(splitter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[];
}

What's this mean:

replace(searchValue: {
  [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; },
  replacer: (substring: string, ...args: any[]) => string
): string;

SearchValue is of type {[Symbol.replace]...} which I think should be string.

Can anyone explain it?

Thanks.

1 Answers

Playground

interface A {
  a():void;
}

interface B {
  [Symbol.replace]():void;
}


interface StringPrototypeReplace0 {
  //
  replace(
    searchValue: {[Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; },
    replacer: (substring: string, ...args: any[]) => string
  ): string;
}

type KEY_A = keyof A; // type KEY_A = "a"
type KEY_B = keyof B; // type KEY_B = typeof Symbol.replace

type P_A = Pick<A, 'a'> // {a:() => void}


type P_B = Pick<RegExp, typeof Symbol.replace>; // two overloads of [Symbol.replace]

// Pick last overload methods
type LastOverload<T> = T extends {
  (...args: infer A1): infer R1;
} ? {(...args:A1): R1}
: T extends {
  (...args: infer A1): infer R1;
  (...args: infer A2): infer R2;
} ? {(...args:A2): R2} : never;

// (string: string ,replacer: (substring: string, ...args: any[]) => string)=> string;
type P_B_LAST = LastOverload<P_B[typeof Symbol.replace]>; 

interface StringPrototypeReplace1 {
  replace(
    searchValue: {[Symbol.replace]:P_B_LAST},
    replacer: Parameters<P_B_LAST>[1]
  ): string;
}

In above code, I tried to write method replace signature without repetition. But event more code is involved. So I guess repeat the signature maybe the best we can do.

Corrections are welcomed.

Related