From 209b1f7749d23860ab0e68c919ff804777a07279 Mon Sep 17 00:00:00 2001 From: Kevin Gibbons Date: Sun, 22 Mar 2020 17:22:20 -0700 Subject: [PATCH] TypeScript: avoid trailing commas on index signatures with only one parameter (#7836) --- changelog_unreleased/typescript/pr-7836.md | 33 +++++++++++++++++ src/language-js/printer-estree.js | 11 +++++- .../__snapshots__/jsfmt.spec.js.snap | 36 +++++++++++++++++++ .../index-signature.ts | 5 +++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 changelog_unreleased/typescript/pr-7836.md diff --git a/changelog_unreleased/typescript/pr-7836.md b/changelog_unreleased/typescript/pr-7836.md new file mode 100644 index 000000000000..8a7156fb6d57 --- /dev/null +++ b/changelog_unreleased/typescript/pr-7836.md @@ -0,0 +1,33 @@ +#### Avoid trailing commas on index signatures with only one parameter ([#7836](https://github.com/prettier/prettier/pull/7836) by [@bakkot](https://github.com/bakkot)) + +TypeScript index signatures technically allow multiple parameters and trailing commas, but it's an error to have multiple parameters there, and Babel's TypeScript parser does not accept them. So Prettier now avoids putting a trailing comma there when you have only one parameter. + + +```ts +// Input +export type A = { + a?: { + [ + x: string + ]: typeof SomeLongLongLongTypeName[keyof typeof SomeLongLongLongTypeName]; + } | null; +}; + +// Prettier stable +export type A = { + a?: { + [ + x: string, + ]: typeof SomeLongLongLongTypeName[keyof typeof SomeLongLongLongTypeName]; + } | null; +}; + +// Prettier master +export type A = { + a?: { + [ + x: string + ]: typeof SomeLongLongLongTypeName[keyof typeof SomeLongLongLongTypeName]; + } | null; +}; +``` diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 81752b18f837..2c76f6388624 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -3259,6 +3259,15 @@ function printPathNoParens(path, options, print, args) { case "TSIndexSignature": { const parent = path.getParentNode(); + // The typescript parser accepts multiple parameters here. If you're + // using them, it makes sense to have a trailing comma. But if you + // aren't, this is more like a computed property name than an array. + // So we leave off the trailing comma when there's just one parameter. + const trailingComma = + n.parameters.length > 1 + ? ifBreak(shouldPrintComma(options) ? "," : "") + : ""; + const parametersGroup = group( concat([ indent( @@ -3267,7 +3276,7 @@ function printPathNoParens(path, options, print, args) { join(concat([", ", softline]), path.map(print, "parameters")), ]) ), - ifBreak(shouldPrintComma(options) ? "," : ""), + trailingComma, softline, ]) ); diff --git a/tests/typescript_error_recovery/__snapshots__/jsfmt.spec.js.snap b/tests/typescript_error_recovery/__snapshots__/jsfmt.spec.js.snap index 69e51fbbd831..c9b4a2b647b6 100644 --- a/tests/typescript_error_recovery/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typescript_error_recovery/__snapshots__/jsfmt.spec.js.snap @@ -173,6 +173,11 @@ type TooLong = { type TooLong81 = { [loooooooooooooooooooooooooong: string, loooooooooooooooooong: string]: string; } type TooLong80 = { [loooooooooooooooooooooooooong: string, looooooooooooooooong: string]: string; } +// note lack of trailing comma in the index signature +type TooLongSingleParam = { + [looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong: string]: string; +} + =====================================output===================================== type A = { [key: string] }; @@ -199,6 +204,13 @@ type TooLong80 = { [loooooooooooooooooooooooooong: string, looooooooooooooooong: string]: string; }; +// note lack of trailing comma in the index signature +type TooLongSingleParam = { + [ + looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong: string + ]: string; +}; + ================================================================================ `; @@ -224,6 +236,11 @@ type TooLong = { type TooLong81 = { [loooooooooooooooooooooooooong: string, loooooooooooooooooong: string]: string; } type TooLong80 = { [loooooooooooooooooooooooooong: string, looooooooooooooooong: string]: string; } +// note lack of trailing comma in the index signature +type TooLongSingleParam = { + [looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong: string]: string; +} + =====================================output===================================== type A = { [key: string] }; @@ -250,6 +267,13 @@ type TooLong80 = { [loooooooooooooooooooooooooong: string, looooooooooooooooong: string]: string; }; +// note lack of trailing comma in the index signature +type TooLongSingleParam = { + [ + looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong: string + ]: string; +}; + ================================================================================ `; @@ -275,6 +299,11 @@ type TooLong = { type TooLong81 = { [loooooooooooooooooooooooooong: string, loooooooooooooooooong: string]: string; } type TooLong80 = { [loooooooooooooooooooooooooong: string, looooooooooooooooong: string]: string; } +// note lack of trailing comma in the index signature +type TooLongSingleParam = { + [looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong: string]: string; +} + =====================================output===================================== type A = { [key: string] }; @@ -301,6 +330,13 @@ type TooLong80 = { [loooooooooooooooooooooooooong: string, looooooooooooooooong: string]: string; }; +// note lack of trailing comma in the index signature +type TooLongSingleParam = { + [ + looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong: string + ]: string; +}; + ================================================================================ `; diff --git a/tests/typescript_error_recovery/index-signature.ts b/tests/typescript_error_recovery/index-signature.ts index 896541357681..55943aec8356 100644 --- a/tests/typescript_error_recovery/index-signature.ts +++ b/tests/typescript_error_recovery/index-signature.ts @@ -12,3 +12,8 @@ type TooLong = { } type TooLong81 = { [loooooooooooooooooooooooooong: string, loooooooooooooooooong: string]: string; } type TooLong80 = { [loooooooooooooooooooooooooong: string, looooooooooooooooong: string]: string; } + +// note lack of trailing comma in the index signature +type TooLongSingleParam = { + [looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong: string]: string; +}