prettier: Formatting breaks @ts-ignore comments

edited by @thorn0, citing this comment:

@ts-ignore ignores one line of code, not one expression or statement (a behavior diametrically opposed to code beautifiers which operate on the AST). It therefore almost always affects code where Prettier condenses or spreads out TypeScript code.

Prettier 1.19.1 Playground link

--parser typescript

Input:

// @ts-ignore
const result = evaluate(chain, opts.filename, args.map(arg => arg.node.value))

Output:

// @ts-ignore
const result = evaluate(
  chain,
  opts.filename,
  args.map(arg => arg.node.value)
);

The original code example is below. Prettier doesn’t break it anymore, but the general problem with @ts-ignore comments hasn’t been solved.

original code example

Prettier 1.15.1 Playground link

# Options (if any):
--single-quote

Input:

export class WebpackTranslateLoader implements TranslateLoader {
  public getTranslation<T>(lang: string): Observable<T> {
    return from(
      // @ts-ignore 
      import('dinamicModule')
    );
  }
}

Output:

export class WebpackTranslateLoader implements TranslateLoader {
  public getTranslation<T>(lang: string): Observable<T> {
    return from(
      import(// @ts-ignore
      "dinamicModule")
    );
  }
}

Expected behavior:

Same as input. The comment is mean to ignore the function call, but by moving the comment inside the function, the meaning of the comment is lost.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 20
  • Comments: 50 (26 by maintainers)

Most upvoted comments

Who writes code like that? 😛

Also, the previously-suggested solution would have the same limitation.

I don’t know anything about the internals of Prettier, but perhaps you could use the location metadata in the AST to ignore all nodes on the line following the comment.

As a workaround, this might work:

Prettier 1.16.4 Playground link

--parser babylon

Input:

function flattenOptions(
  options: ReactSelectOption[]
): ReactSelectOptionObject[] {
  return options.reduce(
    (acc: ReactSelectOptionObject[], option: ReactSelectOption) =>
      option.hasOwnProperty("options")
        // dummy comment to make ts-ignore work
        // @ts-ignore: totally legal thing to do
        ? flattenOptions(option.options)
        // dummy comment to make ts-ignore work
        // @ts-ignore: another totally legal thing to do
        : acc.concat([option]),
    []
  );
}

Output:

function flattenOptions(
  options: ReactSelectOption[]
): ReactSelectOptionObject[] {
  return options.reduce(
    (acc: ReactSelectOptionObject[], option: ReactSelectOption) =>
      option.hasOwnProperty("options")
        ? // dummy comment to make ts-ignore work
          // @ts-ignore: totally legal thing to do
          flattenOptions(option.options)
        : // dummy comment to make ts-ignore work
          // @ts-ignore: another totally legal thing to do
          acc.concat([option]),
    []
  );
}

fwiw, within google we’ve locally patched prettier to treat ts-ignore as prettier-ignore. This seems to work alright.

@glen-84 It’s not worth the trouble. @ts-ignore is like the with statement or the comma operator. We just don’t want Prettier to break them. That’s it. We shouldn’t really care how they look in the end. That said, if you feel like trying to implement a more sophisticated solution, I’ll be glad to review the PR.

I know it’s obvious, but just to mention, it’s not only about @ts-ignore; the same thing goes for eslint-disable comments

Screenshot 2023-07-18 at 20 01 21

Just pinging here, as I just ran into exactly this problem (from earlier in this thread) with ternaries and VSCode: https://github.com/prettier/prettier/issues/5411#issuecomment-461881755

The workaround with dummy comments does work, but it would be great if the underlying problem could be fixed.

NB: Someone mentioned that there is a separate issue for ternaries, but I couldn’t find it. Happy to move this there if someone can point me in the right direction.

Thanks!

Wouldn’t be sufficient either.

// @ts-ignore
const foo = 1; const bar = 2;

@ts-ignore is supposed to be used as a temporary measure. It’s very much like a TODO comment. So fix all your @ts-ignores and now all your code is formatted again. It really looks like a good enough trade-off.

~Also my statement which you cited in the deleted comment is completely bogus, gonna update my comment.~

This comment is completely bogus, ignore it.

Sweet trick @lydell — it works! However a part of me wishes that this could be an internal rule that prettier can automatically work around.

I’m gonna throw in my two cents on a // @ts-ignore use-case I’m trying to use, which prettier seems to break:

function flattenOptions(
  options: ReactSelectOption[]
): ReactSelectOptionObject[] {
  return options.reduce(
    (acc: ReactSelectOptionObject[], option: ReactSelectOption) =>
      option.hasOwnProperty("options")
        // @ts-ignore: totally legal thing to do
        ? flattenOptions(option.options)
        // @ts-ignore: another totally legal thing to do
        : acc.concat([option]),
    []
  );
}

gets formatted like so and means the // @ts-ignore lines aren’t in effect:

function flattenOptions(
  options: ReactSelectOption[]
): ReactSelectOptionObject[] {
  return options.reduce(
    (acc: ReactSelectOptionObject[], option: ReactSelectOption) =>
      option.hasOwnProperty("options")
        ? // @ts-ignore: totally legal thing to do
          flattenOptions(option.options)
        : // @ts-ignore: another totally legal thing to do
          acc.concat([option]),
    []
  );
}

I’ve also tried using // prettier-ignore-start and // prettier-ignore-end and haven’t been able to get VS Code prettier to ignore it…