I have the following code:
const rgxExpressionPropertyName = [/return \w+\.(\w+);?/, /\(?\w+\)?\s*=>\s*\w+\.(\w+);?/];
//for each rgx format
for (var rgx of rgxExpressionPropertyName)
{
...
}
and it's causing typescript compilation error Type 'RegExp[]' must have a '[Symbol.iterator]()' method that returns an iterator.
There are many questions about this error on SO, but they all involve trying to iterate something that Typescript doesn't know is iterable. But in this case, the variable is certainly iterable because it's a const array.
If I replace this with for (var rgx in rgxExpressionPropertyName)
, I do not get the error, but then I don't get to use the nicer for/of
syntax.
It doesn't have anything to do with being an array of Regexp, because I get the same error with number[]
.
What's going on here?
The minimum configuration and code required are:
tsconfig.json:
{
"include": [ "/js/MyUtils.ts"],
"compileOnSave": true,
"compilerOptions":
{
"outFile":"Output.d.ts",
"declaration": true,
"emitDeclarationOnly": true,
"newLine": "CRLF",
"target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
//i don't this does anything (though we do need to figure out modules)
//"module": "ES6", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": [ "dom", "es5" ],
"allowJs": false, /* Allow javascript files to be compiled. */
"strict": false, /* Enable all strict type-checking options. */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}
MyUtils.ts:
const nums = [1, 2, 3]
for (var num of nums)
{
console.log(num)
}
TL;DR: Make sure to set the lib
compiler option to an appropriate environment you are targetting.
lib
and target
doThis happens because your lib
configuration excludes The usage of iterators - an ES6 / ES2015 feature. Note that setting "target": "ES2015"
is not enough - the lib
and target
settings serve different purposes:
target
- affects what syntax will be used in the JavaScript code after compilation.
lib
affects what APIs your code has access to.
Essentially, lib
restricts what environments the code will work on, while target
is in charge of the code the compiler produces.
Here is how that can differ,
target
in shortThe following code
arr.map(x => x + 1);
Using "target": "ES5"
will compile to:
arr.map(function(x) { return x + 1; });
As that is ES5 compliant code - arrow functions were introduced in ES6.
With "target": "ES6"
the compiled code would be
arr.map(x => x + 1);
lib
in shortThis is different from target
as it does not cover syntax. You can always use an arrow function or class
or other syntax features when writing TypeScript, since the syntax is valid. If the target
prohibits some syntax feature (e.g., arrow functions), then transpilation will ensure that the TypeScript source code is converted to valid JavaScript.
However, APIs are entirely separate thing. You cannot use use new Map()
without lib
option covering it, since that is not syntax, so it cannot be transpiled to work.
target
and lib
Using for..of
is a bit special because it can be transpiled but the transpiled code will vary with target
and the API support of the transpiled code can be restricted by lib
.
When using
{
"compilerOptions":
{
"target": "ES5",
"lib": [ "es6" ],
...
}
}
The code
const nums = [1, 2, 3]
for (var num of nums)
{
}
transpiles to
var nums = [1, 2, 3];
for (var _i = 0, nums_1 = nums; _i < nums_1.length; _i++) {
var num = nums_1[_i];
}
Which is valid code given the target and the constraints. However, using the configuration:
{
"compilerOptions":
{
"target": "ES6",
"lib": [ "es5" ],
...
}
}
Then the loop instead transpiles to:
const nums = [1, 2, 3];
for (var num of nums) {
}
Which is now not valid given the constraint on APIs, since this code will not work in an ES5 environment.
By default if you do not set the lib
option, then the default would be determined by target
. So, you should not get conflicting results from compilation.
However, if you do specify lib
then you need to make sure it matches the environment you are planning to run your code on.