diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0567712f11da3..459ed79a0a7c0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4069,7 +4069,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let symbolFromVariable: Symbol | undefined; // First check if module was specified with "export=". If so, get the member from the resolved type - if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(InternalSymbolName.ExportEquals)) { + const isExportEquals = !!(moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(InternalSymbolName.ExportEquals)); + if (isExportEquals) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), nameText, /*skipObjectFunctionPropertyAugment*/ true); } else { @@ -4077,6 +4078,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // if symbolFromVariable is export - get its final target symbolFromVariable = resolveSymbol(symbolFromVariable, dontResolveAlias); + // Check accessibility for named imports from CJS export= modules whose exports are class members + if (!dontResolveAlias && isExportEquals && symbolFromVariable && isImportSpecifier(specifier)) { + checkPropertyAccessibilityAtLocation(specifier, /*isSuper*/ false, /*writing*/ false, getTypeOfSymbol(targetSymbol), symbolFromVariable, name); + } let symbolFromModule = getExportOfModule(targetSymbol, nameText, specifier, dontResolveAlias); if (symbolFromModule === undefined && nameText === InternalSymbolName.Default) { diff --git a/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.errors.txt b/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.errors.txt new file mode 100644 index 0000000000000..9fa17e45d2acb --- /dev/null +++ b/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.errors.txt @@ -0,0 +1,22 @@ +main.ts(1,13): error TS2445: Property 'b' is protected and only accessible within class 'X' and its subclasses. +main.ts(1,16): error TS2341: Property 'c' is private and only accessible within class 'X'. +main.ts(1,25): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. + + +==== module.ts (0 errors) ==== + class X { + public static a = 1; + protected static b = 2; + private static c = 3; + } + export = X; + +==== main.ts (3 errors) ==== + import { a, b, c } from "./module"; + ~ +!!! error TS2445: Property 'b' is protected and only accessible within class 'X' and its subclasses. + ~ +!!! error TS2341: Property 'c' is private and only accessible within class 'X'. + ~~~~~~~~~~ +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. + \ No newline at end of file diff --git a/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.js b/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.js new file mode 100644 index 0000000000000..e063781e363f1 --- /dev/null +++ b/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.js @@ -0,0 +1,25 @@ +//// [tests/cases/compiler/namedImportFromCjsClassExportAccessibility.ts] //// + +//// [module.ts] +class X { + public static a = 1; + protected static b = 2; + private static c = 3; +} +export = X; + +//// [main.ts] +import { a, b, c } from "./module"; + + +//// [module.js] +"use strict"; +class X { +} +X.a = 1; +X.b = 2; +X.c = 3; +module.exports = X; +//// [main.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.symbols b/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.symbols new file mode 100644 index 0000000000000..35109922b3711 --- /dev/null +++ b/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.symbols @@ -0,0 +1,24 @@ +//// [tests/cases/compiler/namedImportFromCjsClassExportAccessibility.ts] //// + +=== module.ts === +class X { +>X : Symbol(X, Decl(module.ts, 0, 0)) + + public static a = 1; +>a : Symbol(X.a, Decl(module.ts, 0, 9)) + + protected static b = 2; +>b : Symbol(X.b, Decl(module.ts, 1, 24)) + + private static c = 3; +>c : Symbol(X.c, Decl(module.ts, 2, 27)) +} +export = X; +>X : Symbol(X, Decl(module.ts, 0, 0)) + +=== main.ts === +import { a, b, c } from "./module"; +>a : Symbol(a, Decl(main.ts, 0, 8)) +>b : Symbol(b, Decl(main.ts, 0, 11)) +>c : Symbol(c, Decl(main.ts, 0, 14)) + diff --git a/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.types b/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.types new file mode 100644 index 0000000000000..73ab2ab300e07 --- /dev/null +++ b/tests/baselines/reference/namedImportFromCjsClassExportAccessibility.types @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/namedImportFromCjsClassExportAccessibility.ts] //// + +=== module.ts === +class X { +>X : X +> : ^ + + public static a = 1; +>a : number +> : ^^^^^^ +>1 : 1 +> : ^ + + protected static b = 2; +>b : number +> : ^^^^^^ +>2 : 2 +> : ^ + + private static c = 3; +>c : number +> : ^^^^^^ +>3 : 3 +> : ^ +} +export = X; +>X : X +> : ^ + +=== main.ts === +import { a, b, c } from "./module"; +>a : number +> : ^^^^^^ +>b : number +> : ^^^^^^ +>c : number +> : ^^^^^^ + diff --git a/tests/cases/compiler/namedImportFromCjsClassExportAccessibility.ts b/tests/cases/compiler/namedImportFromCjsClassExportAccessibility.ts new file mode 100644 index 0000000000000..20b307be01e6c --- /dev/null +++ b/tests/cases/compiler/namedImportFromCjsClassExportAccessibility.ts @@ -0,0 +1,15 @@ +// @target: es2020 +// @module: commonjs +// @strict: true +// @esModuleInterop: true + +// @Filename: module.ts +class X { + public static a = 1; + protected static b = 2; + private static c = 3; +} +export = X; + +// @Filename: main.ts +import { a, b, c } from "./module";