Skip to content
Advertisement

Property ‘replace’ does not exist on type ‘IData’. What is missing?

I am tryign to create a cast function where a string with numbers is received as input, but when using the regex function “replace()” it doesn’t recognize it.

Anyone know how can I declare “replace()” inside type IData?

interface IData{
    data:string | {
        replace: (()=>number),
    };
}

class Cast{

    castString(data:IData){
        return data.toString();
    }

    castNumber(data:IData){
        return data.replace(/D+/g, '');
    }

}

export default new Cast;

Advertisement

Answer

Based on the comments so far, I think that there is a need to shortly explain types in JS (which translates to TS as well).

Primitive types in JavaScript (e.g. string, number and boolean) are no objects with functions, but rather only values. The functions you can call on them (like replace for a string) are actually from the so called Boxed types. They are the Object counterpart to the primitives. They can be used to either explicitly cast (Number("123")) or to wrap the primitive in an object (new Number(123)).

Latter should be avoided, because this id done automatically by JS whenever needed. Like in your case: "34bbb5".replace(...) is changed to new String("34bbb5").replace(...) behind the scenes

How does this information help?

With that in mind, your goal seems to be to define a string type that has a different replace function definition. The new definition was meant to change the behavior of the Sting.replace function. Problem being, that it is only a definition. So, it does not affect the actual String.replace function.

What are your options

A TypeScript interface is only a definition present at compile time. So, by overloading the replace function definition you do not gain any code change. Consequentially, the following interface definition should suite your case just fine.

interface IData {
  data:string
}

Your Cast class seems to have the task to cast the IData either to a string or to a number. The first one is rather simple, as it means to simply return the value of the data attribute.

You used the toString() method of the object that fullfills the IData interface. This actually calls the Object.toString() function which results in "[object Object]".

The second cast method should return a number. Here you already provided most of the code, but you missed to call it on the data attribute (as pointed out by @jcalz). So, you should call it on the data attribute and actually cast it to a number. You can use + or Number() or parseInt() for this. As you only have numbers in the string left, there is no difference in behavior.

The result would look like:

interface IData{
    data:string;
}

class Cast{
    castString(data:IData){
        return data.data.toString();
    }
    castNumber(data:IData){
        return Number(data.data.replace(/D+/g, ''));
    }
}

export default new Cast;

Tip

You could also use object destructuring if you want

castString({data}: IData){
  return data.toString();
}
Advertisement