Search code examples
node.jstypescriptnpmtslintnpx

Node / Typescript / tslint errors on optional chaining operator (?.) in node_modules folder


I have a node script which runs fine on node version up to 17:

$ nvm use 17
Now using node v17.9.1 (npm v8.11.0)
$ cd src
$ npx tsc
$ npx node parser.js
$ cd ..

Beginning with node version 18 it errors because @npmcli is using an optional chaining operator:

$ nvm use 18
Now using node v18.16.0 (npm v9.5.1)
$ cd src
$ npx tsc
/Users/mles/.nvm/versions/node/v18.16.0/lib/node_modules/npm/node_modules/@npmcli/config/lib/index.js:485
        const raw = this.data.get(problem.where).raw?.[problem.from]
                                                     ^

SyntaxError: Unexpected token '.'

I get a similar error on node versions 19, 20, and 21. I'm guessing it has to do with my typescript or tslint setup, that does not like any optional chaining operator. I've tried ignoring any node_modules folder in my tslint.json file, but it does not solve the problem:

{
  "defaultSeverity": "error",
  "extends": [
    "tslint:recommended"
  ],
  "jsRules": {},
  "rules": {
    "no-console": false,
    "object-literal-sort-keys": [
      true,
      "match-declaration-order"
    ],
    "max-line-length": [
      true,
      200
    ],
    "typedef": [
      true,
      "member-variable-declaration",
      "variable-declaration"
    ]
  },
  "rulesDirectory": [],
  "compilerOptions": {
    "skipLibCheck": true
  },
  "linterOptions": {
    "exclude": [
        "node_modules"
    ]
  }
}

My tsconfig.json file:

{
  "compilerOptions": {
    "target": "ESNEXT",             
    "module": "commonjs",           
    "strict": true,                 
    "esModuleInterop": true,        
    "sourceMap": true
  }
}

Any hints how to allow the optional chaining operator in my setup?


Solution

  • You can update your compilerOptions to include the specific rules for optional chaining. This will allow you to keep the strict mode on and keep validating the dependencies.

    Your compilerOptions would look like this:

    {
      "compilerOptions": {
        "target": "ESNEXT",             
        "module": "commonjs",           
        "strict": true,
        "esModuleInterop": true,        
        "sourceMap": true,
        "lib": ["ESNext", "DOM", "ES2020.OptionalChaining", "ES2020.NullishCoalescing"]
      }
    }
    

    (You might need to rebuild your TypeScript project (with npx tsc) afterwards for the change to be applied)