简体   繁体   中英

TypeScript overloading method on base-type string

TypeScript-Version: 1.6

I'm trying to add another overload-function for String s replace -function which should have the following signature:

replace(searchValue: string, replaceValue: any): string;

So it can be used like

"someString".replace("replaceMe", $(evt.target).data("row-id"))

I need any as of .data is defined as:

data(key: string): any;

My String.d.ts (declaration)

interface String {
    /**
      * Replaces text in a string, using a regular expression or search string.
      * @param searchValue A string that represents the regular expression.
      * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
      */
    replace(searchValue: string, replaceValue: any): string;
}

My String.ts (implementation)

String.prototype.replace = (searchValue: string, replaceValue: any):string =>
{
    if (replaceValue instanceof String) {
        var stringReplacement = replaceValue.toString();
        return String.prototype.replace(stringReplacement, replaceValue);
    } else {
        return replaceValue;
    }
}

The following error is thrown and I'm not sure why and how it can be fixed:

Error TS2322 Type '(searchValue: string, replaceValue: any) => string' is not assignable to type '{ (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring...'. Types of parameters 'searchValue' and 'searchValue' are incompatible. Type 'string' is not assignable to type 'RegExp'. Property 'exec' is missing in type 'String'.

Edit #1

I ended up with just the declaration for replace (and removement of the implementation) to satisfy the compiler:

interface String {
    /**
      * Replaces text in a string, using a regular expression or search string.
      * @param searchValue A string that represents the regular expression.
      * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
      */
    replace(searchValue: string, replaceValue: any): string;
}

Is this still wrong as of internally it still calls the replace -function of the library?

Edit #2

If using nothing own Visual Studio is yelling

枯萎

With cast it shows (ReSharper)

ReSharper说

With example 4.1 (MartyIX)

带有变量声明

Doing "someString".replace("replaceMe", $(evt.target).data("row-id")); should work because any can be assigned to string . I'm not sure why you're getting an error, but I would recommend making sure the function signatures with string as the first parameter for replace haven't been removed from lib.d.ts . You can double check that by going to the definition of replace (put cursor on replace and hit F12) and making sure it has all the function signatures shown below. You can also try disabling resharper temporarily to see if that makes the error go away.

By the way, to fix your error with overriding String.prototype.replace , it already has these possible function signatures:

replace(searchValue: string, replaceValue: string): string;
replace(searchValue: string, replacer: (substring: string, ...args: any[]) => string): string;
replace(searchValue: RegExp, replaceValue: string): string;
replace(searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string;

What was written is not compatible when searchValue is a RegExp , so you need to change the function signature to allow both string and RegExp by using a union type:

String.prototype.replace = function(searchValue: string | RegExp, replaceValue: any) {
    // omitted
}

I'm not sure what you're trying to do though because the function will do an infinite loop. Maybe you meant to hold a reference to the original String.prototype.replace and call that? Remember that when you assign to String.prototype.replace you overwrite the original function.

Overall though don't do what's being done here . Look up "don't modify objects you don't own" to see what I mean. It would be better if you create your own separate function to do this because right now this replace function breaks any code that uses it . You'll get really weird behaviour if any library you use uses the replace method and it will be difficult to trace the problem.

My take on this:

1) The following piece of code does not report any errors on my machine:

/// <reference path="typings/jquery/jquery.d.ts" />

"someString".replace("replaceMe", $('#test').data("row-id"));

Are you sure that there is an issue in the first place? What is your setting for the TypeScript compiler (ie how do you compile TS code)?

2) If you need to implement a replace method, you should really consider to create your own module for that otherwise you may cause great confusion for people who read your code:

module Project.Utils {
    export class String {   
        public replace = (searchValue: string, replaceValue: any):string =>
        {
            // some replace implementation
        }
    }
}

3)The implementation is wrong in the first place because you replace String.prototype.replace and then you expect that it will call the native implementation of String.prototype.replace and that is not true. Effectively your implementation does NOT do any replacing functionality at all.

String.prototype.replace = (searchValue: string, replaceValue: any):string =>
{
    if (replaceValue instanceof String) {
        var stringReplacement = replaceValue.toString();
        return String.prototype.replace(stringReplacement, replaceValue);
    } else {
        return replaceValue;
    }
}

4) This codes run perfectly fine in http://www.typescriptlang.org/Playground :

let n:any = 1; 
"someString".replace("replaceMe", n); 

"someString".replace("replaceMe", <any>5); // explicit cast

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM