23

I'm trying to get all ids in Array, and then remove duplicates with React TypeScript.

Here is my code :

const uniqueMuscle = workoutexercices.map((exercice: any) => {
    let exercicesId = exercice.id;
    exercicesId = [...new Set(exercicesId)];
    return exercicesId;
  });

VSCode underlines [...new Set(exercicesId)]; in red and tells me : Type 'Set<unknown>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher

So I went to my ts.config and I changed the value, but still the same error.

Here is my ts.config :

{
  "compilerOptions": {
    "target": "es2015",
I   "downlevelIteration": true
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

Any idea why I keep having this error ?

Johan
  • 2,088
  • 2
  • 9
  • 37
  • I mean, that tsconfig doesn’t have `downlevelIteration` set and the `target` is `es5`, which is older than `es2015`. So if that’s your TS config then of course you’d get that error. You said you “changed the value”. What value did you change and to what did you change it? – jcalz Jul 24 '22 at 15:14
  • @jcalz I changed ez5 by es2015 and added "downlevelIteration": true ? – Johan Jul 24 '22 at 15:19
  • 1
    @Johan - Better to show that edited version *in* the question, than the one you already know doesn't work. – T.J. Crowder Jul 24 '22 at 15:21
  • 1
    Also, what is `exercise.id`? You're using it as an iterable, passing it into `new Set`, and then using the values from the set in an array. That seems odd for an "id". I suppose if the ID is a string that would give you unique characters, but I can't imagine why that would be useful... – T.J. Crowder Jul 24 '22 at 15:25
  • With `target: "es2015"` and `"downlevelIteration": true` (though you don't need it if targeting ES2015), [I don't get an error](https://stackblitz.com/edit/typescript-xs7dts?file=index.ts). – T.J. Crowder Jul 24 '22 at 15:28
  • I have the error, even after restart – Johan Jul 24 '22 at 15:31

7 Answers7

17

The problem is that you want to use a feature that is only available in the ES2015 JavaScript version onwards.

The solution is to update the tsconfig.json file, changing "target" to at least "es2015" (also called "es6").

{
  "compilerOptions": {
    "target": "es2015",
    ...
  }
}

Source: TSConfig Target option

Axel Lopez
  • 418
  • 5
  • 8
6

had same error, setting tsconfig.json from CommonJS to Es modules with target, module, moduleResolution helped me.

my tsconfig.json:

    "compilerOptions": {
        "target": "ES2020",
        "module": "ESNext",
        "moduleResolution": "NodeNext",
        "jsx": "react-jsx",
        "baseUrl": "./",
        "resolveJsonModule": true,
        "esModuleInterop": true
    }
} 
Tonikprofik
  • 86
  • 1
  • 4
4

For those who, as myself, for any reason can't change the target there are alternatives to fix this problem. It's, for instance, possible to remove all duplicates using the Array.prototype.filter method. This exactly the first way to achieve that this answer suggests.

Using the example proposed by the OP, here is what needs to be changed:

One can replace this:

exercicesId = [...new Set(exercicesId)];

With this:

exercicesId = exercicesId.filter((value, index, array) => array.indexOf(value) === index);
Gustavo Straube
  • 3,744
  • 6
  • 39
  • 62
2

try exercicesId = Array.from(new Set(exercicesId));

Rodder
  • 21
  • 1
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center. – DSDmark Jun 22 '23 at 15:27
1

(hijacking) adding a note for others finding this thread

In my React v 18.2 app I got the similar error below when implementing the Recoiljs DebugObserver as described in https://recoiljs.org/docs/guides/dev-tools#observing-all-state-changes

type 'Iterable<RecoilValue>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.

I turns out the Create react app set the configuration in tsconfig to "target": "es5"

When updating the target to 2019 or 2020 I got another error in the DebugObserver

  • Namespace 'React' has no exported member 'Node'.ts(2694)
  • changing the use of "React.Node" to "React.ReactNode" solves the issue as described here (https://stackoverflow.com/a/70332268/2501481)
  • not sure if it is something that has changed in the versions of React or not.
import { useEffect } from "react";
import { useRecoilSnapshot } from "recoil";

//function DebugObserver(): React.Node { // not working with es2019 or es2020
function DebugObserver(): React.ReactNode {
    const snapshot = useRecoilSnapshot();
    useEffect(() => {
      console.debug('The following atoms were modified:');
      for (const node of snapshot.getNodes_UNSTABLE({isModified: true})) {
        console.debug(node.key, snapshot.getLoadable(node));
      }
    }, [snapshot]);
  
    return null;
  }

So tsconfig.json ends up like this

"compilerOptions": {
    "target": "es2020",
    "lib": [
      "dom",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": false, //setting this to false will show errors in node_modules,  
    //Consider setting "skipLibCheck" to false if you are using third-party libraries with TypeScript definitions. 
    //This will help you catch type errors in those libraries. 
    //However, if you encounter performance issues during the type-checking process, set it back to true.
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "jsxImportSource": "react" //Add "jsxImportSource": "react" to use the new JSX transform introduced in React 17, which allows you to use JSX without importing React explicitly.
  },
JimiSweden
  • 744
  • 10
  • 13
0

All you have to do is, go to tsconfig.json file and change the es2015 to es6

enter image description here

Deepak paramesh
  • 495
  • 1
  • 8
  • 19
-1

modify ts config file

...
"target": "ES2015",
"lib": [...,"ES2015"],
...
zhxlp
  • 31
  • 3
  • 1
    1) This doesn't teach the asker anything they don't already know (see their title). 2) lib values corresponding to a target are implied by selecting that target ([docs](https://www.typescriptlang.org/tsconfig#lib)). – starball Sep 05 '22 at 21:25