From c5420beea6d6afe13cb7017ec23e5bbe9ad1792a Mon Sep 17 00:00:00 2001 From: Orta Therox Date: Tue, 23 Jul 2019 09:05:56 -0400 Subject: [PATCH] Prefer default imports over import = when auto-fixing with esModuleInterop being on - fixes #29038 --- src/compiler/utilities.ts | 4 ++++ src/services/codefixes/importFixes.ts | 10 +++++++-- .../importNameCodeFix_ESModuleInterop.ts | 21 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/importNameCodeFix_ESModuleInterop.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f3282d4372300..071a9c25a8f9b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -7289,6 +7289,10 @@ namespace ts { moduleKind === ModuleKind.System; } + export function getEsModuleInterop(compilerOptions: CompilerOptions) { + return compilerOptions.esModuleInterop; + } + export function getEmitDeclarations(compilerOptions: CompilerOptions): boolean { return !!(compilerOptions.declaration || compilerOptions.composite); } diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 8006d1a0cfd04..7d3cf502bd646 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -420,17 +420,22 @@ namespace ts.codefix { function getDefaultLikeExportInfo( moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions, ): { readonly symbol: Symbol, readonly symbolForMeaning: Symbol, readonly name: string, readonly kind: ImportKind.Default | ImportKind.Equals } | undefined { - const exported = getDefaultLikeExportWorker(moduleSymbol, checker); + const exported = getDefaultLikeExportWorker(moduleSymbol, checker, compilerOptions); if (!exported) return undefined; const { symbol, kind } = exported; const info = getDefaultExportInfoWorker(symbol, moduleSymbol, checker, compilerOptions); return info && { symbol, kind, ...info }; } - function getDefaultLikeExportWorker(moduleSymbol: Symbol, checker: TypeChecker): { readonly symbol: Symbol, readonly kind: ImportKind.Default | ImportKind.Equals } | undefined { + function getDefaultLikeExportWorker(moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions): { readonly symbol: Symbol, readonly kind: ImportKind.Default | ImportKind.Equals } | undefined { const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol); if (defaultExport) return { symbol: defaultExport, kind: ImportKind.Default }; const exportEquals = checker.resolveExternalModuleSymbol(moduleSymbol); + + // When ESModule interop is on we want to always use default style instead + if (getEsModuleInterop(compilerOptions)) { + return { symbol: exportEquals, kind: ImportKind.Default }; + } return exportEquals === moduleSymbol ? undefined : { symbol: exportEquals, kind: ImportKind.Equals }; } @@ -550,6 +555,7 @@ namespace ts.codefix { defaultImport === undefined ? undefined : createIdentifier(defaultImport), namedImports.map(n => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(n))), moduleSpecifier, quotePreference)); } + if (namespaceLikeImport) { insertImport(changes, sourceFile, namespaceLikeImport.importKind === ImportKind.Equals ? createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier(namespaceLikeImport.name), createExternalModuleReference(quotedModuleSpecifier)) diff --git a/tests/cases/fourslash/importNameCodeFix_ESModuleInterop.ts b/tests/cases/fourslash/importNameCodeFix_ESModuleInterop.ts new file mode 100644 index 0000000000000..cbd9459f2bf59 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_ESModuleInterop.ts @@ -0,0 +1,21 @@ +/// +// #29038 + +// @allowJs: true +// @checkJs: true +// @esModuleInterop: true +// @moduleResolution: node + +// @Filename: /node_modules/moment.d.ts +////declare function moment(): void; +////export = moment; + +// @Filename: /b.js +////[|moment;|] + +goTo.file("/b.js"); +verify.importFixAtPosition([ +`import moment from "moment"; + +moment;`, +]);