Typescript: 'esnext.array' doesn't enable access to Array.prototype.flat()

Created on 10 Aug 2018  ·  26Comments  ·  Source: microsoft/TypeScript

TypeScript Version: 3.1.0-dev.201xxxxx


Search Terms: esnext, esnext.array, Array.prototype.flat()

Code

// greeter.ts

function greeter(persons: string[]) {
    return "Hello, " + persons.flat().join();
}

var user: string[] = ["Jane User"];

document.body.innerHTML = greeter(user);


// tsconfig.json
{
  "files": [
    "greeter.ts"
  ],
  "compilerOptions": {
    "target": "esnext",
    "lib": [
      "es2017",
      "esnext.array",
      "dom"
    ]
  }
}

Expected behavior:
Should compile successfully. According to MDN, it's an experimental API supported by multiple browsers already.

Actual behavior:
Compilation error:

greeter.ts:2:32 - error TS2339: Property 'flat' does not exist on type 'string[]'.

2 return "Hello, " + persons.flat().join(); ~~~~

Playground Link

Question

Most helpful comment

@Favna I've tried loading the lib configs in your order as well, but that does not work for me.

All 26 comments

.flat is specified in lib.esnext.array.d.ts:

https://github.com/Microsoft/TypeScript/blob/ef7997cb73ce46081cbfebc0edd2a0295ba30c33/lib/lib.esnext.array.d.ts#L152-L222

It feels like something else is going on. It won't work in the playground because it doesn't support changing things like the libs and target.

Your tsconfig.json doesn't contain any files or include properties. How are you compiling greeter.ts? At the moment, the config file would not apply to the greeter.ts in something like Visual Studio code.

@kitsonk , yes, I've made sure flat() is there in lib.esnext.array.d.ts before creating this.

I compiled it with tsc greeter.ts hoping that tsc would pick up tsconfig.json. I've just tried again with files section added (see updated initial post) and the error is the same.

@AbakumovAlexandr try tsc -p . instead...

@kitsonk just tried tsc -p tsconfig.json with the same error.

Does esnext.array + flat() work for you when you're reproducing this project?

$ tsc --version
Version 3.0.1
$ tsc -p .

No errors output, greeter.js that is emitted:

function greeter(persons) {
    return "Hello, " + persons.flat().join();
}
var user = ["Jane User"];
document.body.innerHTML = greeter(user);

I even with typescript@next:

$ tsc --version
Version 3.1.0-dev.20180810
$ tsc -p .

Again, no errors... 🤷‍♂️

@AbakumovAlexandr what's the output of tsc -v ?

@kitsonk I think I've figured out the source of the issue thanks to the feedback from your side!

I've switched local TypeScript versions only, while my global one stayed 2.9.2. So it's always compliled with TS 2.9.2. But in 2.9.2, flat() was called flatten(). That's why it couldn't find it.

Unfortunately, tsc doesn't print its version to the console leaving a room for confusion. If you, guys, feel like you'd like to implement it, let me know and I'll create a different issue for that.

@RyanCavanaugh see my above comment, please.

It does print to the console with --version and most compilers are implicitly silent.

@AbakumovAlexandr I thought I was facing the same issue just now (which is why I even found this open issue to begin with). I have TypeScript v3.2.2 and my lib property in tsconfig was set to "lib": ["es2018", "dom", "esnext.array"], being that I just added the esnext.array value. When I moved esnext.array to the front however ("lib": ["esnext.array", "es2018", "dom"],) the error went away and the code compiled normally.

Just reporting my findings as this may be the resolution for your problem as well, in which case this issue could maybe be closed, or if the order shouldn't matter (not too sure, never faced it before) then changed.

@Favna Thank you for reporting this! This is really interesting. Since I don't think the order of libs should matter, this also could be a clue for TS team to figure the issue out.

@AbakumovAlexandr Is there a solution for this? I am receiving compile errors even with "lib": ["es6", "dom", "esnext.array"] in my tsconfig Version 3.3.1.

Compile error message: TS2339: Property 'flat' does not exist on type 'IResult[][]'.

@ernie-h please read my solution above

@Favna I've tried loading the lib configs in your order as well, but that does not work for me.

@ernie-h I've got 2 more ideas then

  1. What is your NodeJS version (node -v)? I know for a fact that on runkit.com array.prototype.flat is not available in Node 10 LTS, but it is when setting it to Node 11 Current. So if you have lower, consider upgrading. If you use Linux or MacOS you could consider using NVM so you can switch back easily if that's not the resolution.

Note that I personally use Node 11.

  1. Here is an exact copy of my tsconfig, maybe you need to configure other settings, such as the moduleResolution to node
{
    "compilerOptions": {
        "outDir": "dist/",
        "rootDir": "./src",
        "forceConsistentCasingInFileNames": true,
        "esModuleInterop": true,
        "lib": ["esnext.array", "es2018", "dom"],
        "target": "es6",
        "module": "commonjs",
        "moduleResolution": "node",
        "newLine": "lf",
        "noFallthroughCasesInSwitch": true,
        "noImplicitAny": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noUnusedLocals": true,
        "removeComments": true,
        "resolveJsonModule": true
    },
    "include": ["src/**/*.ts"],
    "exclude": ["node_modules", "dist", "src/**/*.js"]
}

Updating to Node 11 also resolved this issue for me. The ordering of items in lib does not seem to have an effect, nor does moduleResolution.

Ye Node 11 is the reason why it works as it has the feature internally (and also the fact that the newer V8 engine it has supports it). I think on that note this issue can pretty much be closed. Maybe the feature will eventually be backported to LTS (V10 at time of writing) but that is far outside the scope of this issue.

I'm having a similar problem, it looks like TS is not transpiling the .flat() method to previous versions of node, like it would do for async/await for example.

Node: v10.16.0
Typescript: v3.5.2

{
  "compilerOptions": {
    "incremental": true,
    "target": "es2018",
    "module": "commonjs",
    "lib": ["esnext"],
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

```ts
const flatArr = [[1], [2]].flat().join(',');
console.log(flatArr);


To compile, I'm running the command `npx tsc -p .`

The output is:
```js
"use strict";
const flatArr = [[1], [2]].flat().join(',');
console.log(flatArr);

The output is wrong because in the target (es2018), Array.prototype.flat does not exists.

TypeScript has never downleveled method calls to built-in APIs

Thank you for your reply Ryan.
I find this a bit confusing, how does TS decide what to transpile and what not to?
Like decorators, async/await yes, but built in APIs no? Is it documented anywhere?

TypeScript transpiles language syntax, not functionality. async/await is language syntax, Array.prototype.flat() is functionality. Items described in a type library (lib) are not transpiled.

Even with syntax there are certain caveats, like --downlevelIteration is behind a flag, because it requires that other functionality needs to be polyfilled in environments where it is targeted, which TypeScript won't provide.

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.

How can I get this error to go away since I'm fine with not supporting IE and don't want TS to bloat my bundle with any polyfills? I tried "target": "ES2019" but makes no difference.

don't want TS to bloat my bundle with any polyfills

TypeScript never generates polyfills, so you don't need to do anything

don't want TS to bloat my bundle with any polyfills

TypeScript never generates polyfills, so you don't need to do anything

Ohhhh I see, good to know 👌

Was this page helpful?
0 / 5 - 0 ratings