TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Deprecated decorator factory APIs throw "Invalid arguments" runtime error

Open frigus02 opened this issue 3 years ago • 0 comments

Bug Report

The following factory methods, that got deprecated in 4.8, throw an "Invalid arguments" type error at runtime, if the body parameter is not undefined:

t.factory.createConstructorDeclaration(decorators, modifiers, parameters, body);
t.factory.updateConstructorDeclaration(ctor, decorators, modifiers, parameters, body);

🔎 Search Terms

Invalid arguments, createConstructorDeclaration, updateConstructorDeclaration

🕗 Version & Regression Information

  • This changed between versions 4.7.4 and 4.8.0-dev.20220809

⏯ Playground Link

I don't think this can be reproduced in the playground.

Playground link with relevant code

💻 Code

To reproduce, you can:

$ mkdir repro
$ npm init --yes
$ npm install [email protected]

Add the following code in a file index.js. Then run node index.js.

const ts = require('typescript');

const block = ts.factory.createBlock([]);

// works
const ctor = ts.factory.createConstructorDeclaration(
  /* modifiers */ undefined,
  /* parameters */ [],
  /* body */ block,
);

// works
const _updatedCtorNewApi = ts.factory.updateConstructorDeclaration(
  ctor,
  /* modifiers */ ctor.modifiers,
  /* parameters */ ctor.parameters,
  /* body */ ctor.body,
);

// throws TypeError("Invalid arguments");
const _ctorOldApi = ts.factory.createConstructorDeclaration(
  /* decorators */ undefined,
  /* modifiers */ undefined,
  /* parameters */ [],
  /* body */ block,
);

// throws TypeError("Invalid arguments");
const _updatedCtorDeprecatedApi = ts.factory.updateConstructorDeclaration(
  ctor,
  /* decorators */ ctor.decorators,
  /* modifiers */ ctor.modifiers?.filter(ts.isModifier),
  /* parameters */ ctor.parameters,
  /* body */ ctor.body,
);

🙁 Actual behavior

The deprecated functions createConstructorDeclaration and updateConstructorDeclaration throw an error at runtime. This makes it hard to write code, which works with both TypeScript 4.7 and 4.8.

🙂 Expected behavior

No error 🙂

🕵️ Cause

If I understand the deprecation function overload logic correctly, the issue is here:

https://github.com/microsoft/TypeScript/blob/3c3909b8d0a3d81cf320a84dac373eac19de3a7a/src/deprecatedCompat/4.8/mergeDecoratorsAndModifiers.ts#L538

https://github.com/microsoft/TypeScript/blob/3c3909b8d0a3d81cf320a84dac373eac19de3a7a/src/deprecatedCompat/4.8/mergeDecoratorsAndModifiers.ts#L566

This should use isBlock(body) (without the negation).

frigus02 avatar Aug 10 '22 14:08 frigus02