147

I want to use replaceAll in typescript and angular 10.

But I get this error: Property 'replaceAll' does not exist on type 'string'.

This is my code:

let date="1399/06/08"
console.log(date.replaceAll('/', '_'))

Output: 13990608

How can fix my typescript to show me this function?

Mady Daby
  • 1,271
  • 6
  • 18
behroozbc
  • 1,992
  • 2
  • 12
  • 25
  • 1
    TypeScript can't magically add a function that your browser doesn't implement. You'll need to implement one of the replacement methods mentioned in the linked question in [Michael D's answer](https://stackoverflow.com/a/63616514/215552). – Heretic Monkey Aug 27 '20 at 13:08
  • 7
    `date.split('/').join('_')` you can use this as of now. Although you can update to chrome85. – Jai Aug 27 '20 at 13:09
  • 9
    I want to use in vscode I have this error in vscode – behroozbc Aug 27 '20 at 13:09
  • @behroozbc you can try with latest typescript version. – Jai Aug 27 '20 at 13:10

14 Answers14

146

You should be able to add those typings through your tsconfig.json. Add "ES2021.String" to lib inside compilerOptions.

Your tsconfig should then look something like this:

{
    ...,
    "compilerOptions": {
        ...,
        "lib": [
          ...,
          "ES2021.String"
        ]
    }
}

The replaceAll method is defined inside lib.es2021.string.d.ts as follows:

interface String {
    /**
     * Replace all instances of a substring in a string, using a regular expression or search string.
     * @param searchValue A string to search for.
     * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
     */
    replaceAll(searchValue: string | RegExp, replaceValue: string): string;

    /**
     * Replace all instances of a substring in a string, using a regular expression or search string.
     * @param searchValue A string to search for.
     * @param replacer A function that returns the replacement text.
     */
    replaceAll(searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string;
}
behroozbc
  • 1,992
  • 2
  • 12
  • 25
Josef
  • 2,869
  • 2
  • 22
  • 23
  • found the `lib.esnext.string.d.ts` file the functions are declared as in your code not sure what you mean by "add those typings through your tsconfig.json" can you elaborate – Kukula Mula May 04 '21 at 14:04
  • 3
    @KukulaMula I added a template to my answer. What I meant was, to add `ESNext.String` to `lib` inside you `tsconfig.json`. – Josef May 04 '21 at 16:17
  • 5
    This removes the lint error but when I try to run, I get an error saying `An unhandled exception occurred: tsconfig.json:21:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015',...` with a long list of options but none of them are `ESNext.String` and it won't compile. – Stack Underflow Jul 29 '21 at 20:39
  • @StackUnderflow Maybe your TS version is too low, I believe it was added in TS 2.4, following this [commit](https://github.com/microsoft/TypeScript/commit/451561ec8d793309ca9daa438f22764dd0ef440a#diff-c78e322b21c3cc648f5d6f259f3f1fea58f1165da8347b40385c08c2c8e76ef7) – Josef Jul 30 '21 at 07:04
  • 1
    @Josef mine is 3.8.3, not the latest but not too old. – Stack Underflow Jul 30 '21 at 07:14
  • @StackUnderflow Not sure, you might have an entirely different problem. Search for the `lib.esnext.string.d.ts` file inside `node_modules/typescript/lib`, if its not there your versions don't match up. Or update/reinstall TS as a whole. – Josef Jul 30 '21 at 08:33
  • @Josef You're right. I thought something was fishy because I updated it earlier, now I realize the version Angular is using doesn't match the global version. `tsc -v` shows `4.3.5` but `ng --version` shows `3.8.3`. Any suggestions to resolve this? – Stack Underflow Jul 30 '21 at 08:45
  • @Josef When I updated it I used `npm install -g typescript@latest` and this is what I find when I search for how to update the Angular typescript. – Stack Underflow Jul 30 '21 at 08:47
  • @StackUnderflow That should update TS for you global `ng` but if not specified otherwise angular will use your local version if they don't match. Therefore you should skip the `-g` flag when updating you local repo. – Josef Jul 30 '21 at 09:17
  • @Josef Yes, that looked like it was going to work but it seems like I need to upgrade Angular. I have Angular version 9.1.12 and it was complaining that it `requires TypeScript >=3.6.4 and <3.9.0 but 4.3.5 was found instead.` Thanks for your help. – Stack Underflow Jul 30 '21 at 09:45
  • this worked for me in react-native mixed ts and js project I added them in `tsconfig.json` and `jsconfig.json` files as: `"lib": ["es6", "ES2021.String"]` – Ramy El-Basyouni Dec 23 '21 at 13:42
  • Surely this is just like adding a .d.ts file? It doesn't actually add a shim / polyfill for older browsers. iOS 12/13 still would need a polyfill. So I'm very confused why nobody else has mentioned that. Sure for Chrome this is fine but not older Safari. – Simon_Weaver Feb 19 '22 at 23:14
  • Very old browsers would need a polyfill, but it' actually quite well [supported](https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren#browser_compatibility). – Josef Feb 20 '22 at 08:33
  • write in lowercase if it doesn't work "es2021.String" – Georges Feungap Mar 23 '22 at 07:32
120

You may solve the problem using RegExp and global flag. The global flag is what makes replace run on all occurrences.

"1399/06/08".replace(/\//g, "_") // "1399_06_08"
Zoe
  • 27,060
  • 21
  • 118
  • 148
strdr4605
  • 3,796
  • 2
  • 16
  • 26
  • 29
    this doesn't "resolve the problem". This is another way to replace all the occurrences. But if you want to continue using replaceAll, this doesn't resolve the issue of the OP. – bokkie Dec 06 '20 at 22:38
  • 11
    This question is about TypeScript compatibility with `String.replaceAll()` not a request for a workaround. – Mohammad Moallemi Sep 28 '21 at 11:40
  • 3
    @bokkie In my case it solved the issue. I'm using react native and changing the compiler options doesn't actually update the javascript, so this is really the *only* solution. – ICW Mar 03 '22 at 19:48
19

From the docs:

As of August 2020 the replaceAll() method is supported by Firefox but not by Chrome. It will become available in Chrome 85.

Meanwhile you could find multiple other methods here.

Screenshot for possible future readers:

enter image description here

ruth
  • 29,535
  • 4
  • 30
  • 57
9

That is because TypeScript does not recognize newer methods, than his current JavaScript version. String.replaceAll() is defined is ES2021.

You have to add the lib in compilerOptions, on the tsconfig.json file.

The value of lib must be either: ["ES2021"], or specifically the string typing ["ES2021.String"].

Add the following on the tsconfig.json file:

{
  ...
  "compilerOptions": {
    "lib": ["ES2021"]
  ...
}
Axel Lopez
  • 418
  • 5
  • 8
8

Just Use this function

    let date="1399/06/08"
    
    console.log(date.split('/').join('_'))
Mansour Alnasser
  • 4,446
  • 5
  • 40
  • 51
  • This was my first thought to solve my problem, but I'm sure there's a more efficient way. Using a RegEx seems the way to go – Kieran101 Feb 20 '21 at 16:53
  • 1
    The question asked is "How can fix my typescript to show me this function?". A valid answer obviously is not "use my function instead", even more when there is a clean answer to that (fix the ES version) :) – mhombach Apr 08 '22 at 07:50
7

You can create a file

myOwnTypes.d.ts

at the root of your angular project and add the following code:

interface String {
    replaceAll(input: string, output : string): any;
}

That will tell typescript that strings has this property.

Now replaceAll is supported in Chrome and Firefox but is always good to check the caniuse to check if it fits your needs.

https://caniuse.com/?search=replaceAll

If this works for you upvotes are more than welcome, Im starting with this stackoverflow account and would appreciate the support :)

2

Chrome supports replaceAll so it is safe to use. However typescript still issues an error, so you may cast your string to any, in order to overcome that obstacle.

const date: any ="1399/06/08"
console.log(date.replaceAll('/','_'))
Nathan Arthur
  • 8,287
  • 7
  • 55
  • 80
Ran
  • 747
  • 6
  • 8
2

If anyone is still having this issue, add this to your tsconfig.json

{
    ...,
    "compilerOptions": {
        ...,
        "lib": [
          ...,
          "esnext.string"
        ]
    }
}
2

A simple alternative to replace all using RegExp.

let subject = '1399/06/08';

let substring = '/';
let replacement = '_';

let newSubject = subject.replace(new RegExp(substring, 'g'), replacement);

console.log(newSubject);

Notice that you can make it as a function that takes substring and replacement as string inputs, which is practical.

My use-case was creating an Angular "Replace" Pipe.

Ismail Hachimi
  • 653
  • 6
  • 11
2

This can also happen with a correct tsconfig if the file is not used/imported anywhere and not part of tsconfig.files

user5480949
  • 1,410
  • 1
  • 15
  • 22
  • This helped solve my problem, thanks. My issue was I was missing files in the `includes` part of my `tsconfig.json`. Updating `includes` by adding my scripts directory fixed it. – TestWell Jun 28 '23 at 14:54
2

Another possible solution: I had this issue but my tsconfig target was set to "es2021". The cause, there was also one lib being specified. So by using the lib and the target, it overrided the defaults to the lib. The solution completely remove the lib or add it to the lib options.

Example: "compilerOptions":{ ..."target": "ES2021" }

or

"complierOptions":{
"target": "ES2021", "lib": [ ..., "ES2021.String" ],

Kman
  • 76
  • 4
  • This worked for me. I also had to make sure that my package was set to Node > 15 as well my active Node interpreter with nvm – AvidDabbler Jun 03 '23 at 14:47
0

According to MDN Web Docs,

"to perform a global search and replace, include the g switch in the regular expression".

So, you can try doing:

const date="1399/06/08"
const forwardSlashRegex = /(\/)/g;
console.log(date.replace(forwardSlashRegex, '_'));

This automatically replaces all forward slashes with the underscore. Make sure to also keep the /g global indicator at the end of the regex, as it allows JS to know that you want to replace ALL places where the forward slash occurs.

For more info on the use of regex indicators, refer to the following very useful guide: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

Farhan Kassam
  • 121
  • 1
  • 2
0

In latest versions, you need to set the target attribute in compilerOptions.

{
"compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021", // add this line to use ES2021
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false,
    "noUnusedLocals": false,
    "paths": {
        "@/*": ["src/*"],
        "@auth/*": ["src/auth/*"],
        "@aws/*": ["src/aws/*"],
        "@common/*": ["src/common/*"],
        "@conig/*": ["src/conig/*"],
        "@schemas/*": ["src/schemas/*"],
    }
}}
Sanan Ali
  • 2,349
  • 1
  • 24
  • 34
0

I had the same issue. It seems like the issue is due to primitive string. I converted my string variable to String object and then the replaceAll() method did not cause runtime error.

Nealesh
  • 629
  • 6
  • 12