From 30d5a2dc2f996be9f24067bf0a8847f11ae412c9 Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk Date: Sun, 30 Aug 2026 20:06:18 +0300 Subject: [PATCH 1/2] fix(62179): report non-string-literal values in import type attributes --- tsc/internal/checker/checker.go | 13 ++---- tsc/internal/checker/grammarchecks.go | 13 ++++++ .../conformance/importAttributes12.errors.txt | 46 +++++++++++++++++++ .../importAttributes/importAttributes12.ts | 35 ++++++++++++++ 4 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 tsc/testdata/baselines/reference/conformance/importAttributes12.errors.txt create mode 100644 tsc/testdata/tests/cases/conformance/importAttributes/importAttributes12.ts diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index fb3c33c01b814..00cdfddc13604 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -3334,7 +3334,9 @@ func (c *Checker) checkTemplateLiteralType(node *ast.Node) { func (c *Checker) checkImportType(node *ast.Node) { c.checkSourceElement(node.AsImportTypeNode().Argument) if attributes := node.AsImportTypeNode().Attributes; attributes != nil { - c.getResolutionModeOverride(attributes.AsImportAttributes(), true /*reportErrors*/) + importAttributes := attributes.AsImportAttributes() + c.checkGrammarImportAttributeValues(importAttributes) + c.getResolutionModeOverride(importAttributes, true /*reportErrors*/) } c.checkTypeReferenceOrImport(node) } @@ -5441,14 +5443,9 @@ func (c *Checker) checkExternalImportOrExportDeclaration(node *ast.Node) bool { if !ast.IsImportEqualsDeclaration(node) { attributes := ast.GetImportAttributes(node) if attributes != nil { - hasError := false - for _, attr := range attributes.AsImportAttributes().Attributes.Nodes { - if !ast.IsStringLiteral(attr.AsImportAttribute().Value) { - hasError = true - c.error(attr.AsImportAttribute().Value, diagnostics.Import_attribute_values_must_be_string_literal_expressions) - } + if c.checkGrammarImportAttributeValues(attributes.AsImportAttributes()) { + return false } - return !hasError } } return true diff --git a/tsc/internal/checker/grammarchecks.go b/tsc/internal/checker/grammarchecks.go index be8c0af0e6fcb..5e493e5abd770 100644 --- a/tsc/internal/checker/grammarchecks.go +++ b/tsc/internal/checker/grammarchecks.go @@ -2120,6 +2120,19 @@ func (c *Checker) checkGrammarImportClause(node *ast.ImportClause) bool { return false } +func (c *Checker) checkGrammarImportAttributeValues(node *ast.ImportAttributes) bool { + hasError := false + for _, attribute := range node.Attributes.Nodes { + value := attribute.AsImportAttribute().Value + if ast.IsStringLiteral(value) { + continue + } + hasError = true + c.error(value, diagnostics.Import_attribute_values_must_be_string_literal_expressions) + } + return hasError +} + func (c *Checker) checkGrammarTypeOnlyNamedImportsOrExports(namedBindings *ast.Node) bool { nodeList := namedBindings.ElementList() for _, specifier := range nodeList.Nodes { diff --git a/tsc/testdata/baselines/reference/conformance/importAttributes12.errors.txt b/tsc/testdata/baselines/reference/conformance/importAttributes12.errors.txt new file mode 100644 index 0000000000000..aeb46337ac245 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/importAttributes12.errors.txt @@ -0,0 +1,46 @@ +importAttributes12.ts(10,12): error TS2858: Import attribute values must be string literal expressions. +importAttributes12.ts(16,28): error TS2858: Import attribute values must be string literal expressions. +importAttributes12.ts(22,28): error TS2858: Import attribute values must be string literal expressions. +importAttributes12.ts(28,28): error TS2858: Import attribute values must be string literal expressions. + + +==== importAttributes12.ts (4 errors) ==== + declare module "dependency" { + export interface Type {} + } + + type T1 = typeof import("dependency", { with: { "resolution-mode": "import" } }); + type T2 = import("dependency", { with: { "resolution-mode": "require" } }).Type; + + type T3 = typeof import("dependency", { + with: { + a: (() => "value")(), + ~~~~~~~~~~~~~~~~~ +!!! error TS2858: Import attribute values must be string literal expressions. + }, + }); + + type T4 = import("dependency", { + with: { + "resolution-mode": (() => "import")(), + ~~~~~~~~~~~~~~~~~~ +!!! error TS2858: Import attribute values must be string literal expressions. + }, + }).Type; + + type T5 = import("dependency", { + with: { + "resolution-mode": 0, + ~ +!!! error TS2858: Import attribute values must be string literal expressions. + }, + }).Type; + + type T6 = import("dependency", { + with: { + "resolution-mode": `import`, + ~~~~~~~~ +!!! error TS2858: Import attribute values must be string literal expressions. + }, + }).Type; + \ No newline at end of file diff --git a/tsc/testdata/tests/cases/conformance/importAttributes/importAttributes12.ts b/tsc/testdata/tests/cases/conformance/importAttributes/importAttributes12.ts new file mode 100644 index 0000000000000..b4d8e6a29f34f --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/importAttributes/importAttributes12.ts @@ -0,0 +1,35 @@ +// @target: esnext +// @module: esnext +// @noEmit: true +// @noTypesAndSymbols: true + +declare module "dependency" { + export interface Type {} +} + +type T1 = typeof import("dependency", { with: { "resolution-mode": "import" } }); +type T2 = import("dependency", { with: { "resolution-mode": "require" } }).Type; + +type T3 = typeof import("dependency", { + with: { + a: (() => "value")(), + }, +}); + +type T4 = import("dependency", { + with: { + "resolution-mode": (() => "import")(), + }, +}).Type; + +type T5 = import("dependency", { + with: { + "resolution-mode": 0, + }, +}).Type; + +type T6 = import("dependency", { + with: { + "resolution-mode": `import`, + }, +}).Type; From dd7a674bcabe4d66bf8d5fd0de390057a88e5688 Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk Date: Tue, 1 Sep 2026 22:18:27 +0300 Subject: [PATCH 2/2] update baseline --- .../conformance/importAttributes12.errors.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tsc/testdata/baselines/reference/conformance/importAttributes12.errors.txt b/tsc/testdata/baselines/reference/conformance/importAttributes12.errors.txt index aeb46337ac245..0e1c8f0e4524a 100644 --- a/tsc/testdata/baselines/reference/conformance/importAttributes12.errors.txt +++ b/tsc/testdata/baselines/reference/conformance/importAttributes12.errors.txt @@ -1,10 +1,13 @@ importAttributes12.ts(10,12): error TS2858: Import attribute values must be string literal expressions. importAttributes12.ts(16,28): error TS2858: Import attribute values must be string literal expressions. +importAttributes12.ts(21,11): error TS2322: Type '{ "resolution-mode": 0; }' is not assignable to type 'ImportAttributes'. + Property 'resolution-mode' is incompatible with index signature. + Type 'number' is not assignable to type 'string'. importAttributes12.ts(22,28): error TS2858: Import attribute values must be string literal expressions. importAttributes12.ts(28,28): error TS2858: Import attribute values must be string literal expressions. -==== importAttributes12.ts (4 errors) ==== +==== importAttributes12.ts (5 errors) ==== declare module "dependency" { export interface Type {} } @@ -30,10 +33,16 @@ importAttributes12.ts(28,28): error TS2858: Import attribute values must be stri type T5 = import("dependency", { with: { + ~ "resolution-mode": 0, + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ !!! error TS2858: Import attribute values must be string literal expressions. }, + ~~~~~ +!!! error TS2322: Type '{ "resolution-mode": 0; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'resolution-mode' is incompatible with index signature. +!!! error TS2322: Type 'number' is not assignable to type 'string'. }).Type; type T6 = import("dependency", {