mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
Validate JSON imports into ESM in --module nodenext (#60019)
This commit is contained in:
parent
278f260d0d
commit
9ad213fa8f
@ -163,7 +163,6 @@ import {
|
||||
EmitResolver,
|
||||
EmitTextWriter,
|
||||
emptyArray,
|
||||
endsWith,
|
||||
EntityName,
|
||||
EntityNameExpression,
|
||||
EntityNameOrEntityNameExpression,
|
||||
@ -265,6 +264,7 @@ import {
|
||||
getContainingClassStaticBlock,
|
||||
getContainingFunction,
|
||||
getContainingFunctionOrClassStaticBlock,
|
||||
getDeclarationFileExtension,
|
||||
getDeclarationModifierFlagsFromSymbol,
|
||||
getDeclarationOfKind,
|
||||
getDeclarationsOfKind,
|
||||
@ -3702,11 +3702,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return usageMode === ModuleKind.ESNext && targetMode === ModuleKind.CommonJS;
|
||||
}
|
||||
|
||||
function isOnlyImportableAsDefault(usage: Expression) {
|
||||
function isOnlyImportableAsDefault(usage: Expression, resolvedModule?: Symbol) {
|
||||
// In Node.js, JSON modules don't get named exports
|
||||
if (ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) {
|
||||
const usageMode = getEmitSyntaxForModuleSpecifierExpression(usage);
|
||||
return usageMode === ModuleKind.ESNext && endsWith((usage as StringLiteralLike).text, Extension.Json);
|
||||
if (usageMode === ModuleKind.ESNext) {
|
||||
resolvedModule ??= resolveExternalModuleName(usage, usage, /*ignoreErrors*/ true);
|
||||
const targetFile = resolvedModule && getSourceFileOfModule(resolvedModule);
|
||||
return targetFile && (isJsonSourceFile(targetFile) || getDeclarationFileExtension(targetFile.fileName) === ".d.json.ts");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -3776,7 +3780,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (!specifier) {
|
||||
return exportDefaultSymbol;
|
||||
}
|
||||
const hasDefaultOnly = isOnlyImportableAsDefault(specifier);
|
||||
const hasDefaultOnly = isOnlyImportableAsDefault(specifier, moduleSymbol);
|
||||
const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier);
|
||||
if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) {
|
||||
if (hasExportAssignmentSymbol(moduleSymbol) && !allowSyntheticDefaultImports) {
|
||||
@ -3961,7 +3965,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
let symbolFromModule = getExportOfModule(targetSymbol, nameText, specifier, dontResolveAlias);
|
||||
if (symbolFromModule === undefined && nameText === InternalSymbolName.Default) {
|
||||
const file = moduleSymbol.declarations?.find(isSourceFile);
|
||||
if (isOnlyImportableAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) {
|
||||
if (isOnlyImportableAsDefault(moduleSpecifier, moduleSymbol) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) {
|
||||
symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
|
||||
}
|
||||
}
|
||||
@ -3969,7 +3973,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const symbol = symbolFromModule && symbolFromVariable && symbolFromModule !== symbolFromVariable ?
|
||||
combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) :
|
||||
symbolFromModule || symbolFromVariable;
|
||||
if (!symbol) {
|
||||
|
||||
if (isImportOrExportSpecifier(specifier) && isOnlyImportableAsDefault(moduleSpecifier, moduleSymbol) && nameText !== InternalSymbolName.Default) {
|
||||
error(name, Diagnostics.Named_imports_from_a_JSON_file_into_an_ECMAScript_module_are_not_allowed_when_module_is_set_to_0, ModuleKind[moduleKind]);
|
||||
}
|
||||
else if (!symbol) {
|
||||
errorNoModuleMemberSymbol(moduleSymbol, targetSymbol, node, name);
|
||||
}
|
||||
return symbol;
|
||||
@ -47779,6 +47787,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers);
|
||||
}
|
||||
if (checkExternalImportOrExportDeclaration(node)) {
|
||||
let resolvedModule;
|
||||
const importClause = node.importClause;
|
||||
if (importClause && !checkGrammarImportClause(importClause)) {
|
||||
if (importClause.name) {
|
||||
@ -47793,12 +47802,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
else {
|
||||
const moduleExisted = resolveExternalModuleName(node, node.moduleSpecifier);
|
||||
if (moduleExisted) {
|
||||
resolvedModule = resolveExternalModuleName(node, node.moduleSpecifier);
|
||||
if (resolvedModule) {
|
||||
forEach(importClause.namedBindings.elements, checkImportBinding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isOnlyImportableAsDefault(node.moduleSpecifier, resolvedModule) && !hasTypeJsonImportAttribute(node)) {
|
||||
error(node.moduleSpecifier, Diagnostics.Importing_a_JSON_file_into_an_ECMAScript_module_requires_a_type_Colon_json_import_attribute_when_module_is_set_to_0, ModuleKind[moduleKind]);
|
||||
}
|
||||
}
|
||||
else if (noUncheckedSideEffectImports && !importClause) {
|
||||
void resolveExternalModuleName(node, node.moduleSpecifier);
|
||||
@ -47807,6 +47820,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
checkImportAttributes(node);
|
||||
}
|
||||
|
||||
function hasTypeJsonImportAttribute(node: ImportDeclaration) {
|
||||
return !!node.attributes && node.attributes.elements.some(attr => getTextOfIdentifierOrLiteral(attr.name) === "type" && tryCast(attr.value, isStringLiteralLike)?.text === "json");
|
||||
}
|
||||
|
||||
function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) {
|
||||
if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) {
|
||||
// If we hit an import declaration in an illegal context, just bail out to avoid cascading errors.
|
||||
|
||||
@ -1826,6 +1826,14 @@
|
||||
"category": "Error",
|
||||
"code": 1542
|
||||
},
|
||||
"Importing a JSON file into an ECMAScript module requires a 'type: \"json\"' import attribute when 'module' is set to '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 1543
|
||||
},
|
||||
"Named imports from a JSON file into an ECMAScript module are not allowed when 'module' is set to '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 1544
|
||||
},
|
||||
|
||||
"The types of '{0}' are incompatible between these types.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -10517,9 +10517,10 @@ export function getDeclarationFileExtension(fileName: string): string | undefine
|
||||
return standardExtension;
|
||||
}
|
||||
if (fileExtensionIs(fileName, Extension.Ts)) {
|
||||
const index = getBaseFileName(fileName).lastIndexOf(".d.");
|
||||
const baseName = getBaseFileName(fileName);
|
||||
const index = baseName.lastIndexOf(".d.");
|
||||
if (index >= 0) {
|
||||
return fileName.substring(index);
|
||||
return baseName.substring(index);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
78
tests/baselines/reference/nodeModulesJson.errors.txt
Normal file
78
tests/baselines/reference/nodeModulesJson.errors.txt
Normal file
@ -0,0 +1,78 @@
|
||||
/loosey.cts(1,36): error TS2856: Import attributes are not allowed on statements that compile to CommonJS 'require' calls.
|
||||
/loosey.cts(6,9): error TS2339: Property 'default' does not exist on type '{ version: number; }'.
|
||||
/main.mts(2,22): error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
|
||||
/main.mts(3,19): error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
|
||||
/main.mts(7,21): error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
|
||||
/main.mts(8,10): error TS1544: Named imports from a JSON file into an ECMAScript module are not allowed when 'module' is set to 'NodeNext'.
|
||||
/main.mts(10,9): error TS2339: Property 'version' does not exist on type '{ default: { version: number; }; }'.
|
||||
|
||||
|
||||
==== /node_modules/not.json/package.json (0 errors) ====
|
||||
{
|
||||
"name": "not.json",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"exports": "./index.js"
|
||||
}
|
||||
|
||||
==== /node_modules/not.json/index.d.ts (0 errors) ====
|
||||
export function oops(json: string): any;
|
||||
|
||||
==== /node_modules/actually-json/package.json (0 errors) ====
|
||||
{
|
||||
"name": "actually-json",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.json",
|
||||
"./typed": "./typed.d.json.ts"
|
||||
}
|
||||
}
|
||||
|
||||
==== /node_modules/actually-json/index.json (0 errors) ====
|
||||
{}
|
||||
|
||||
==== /node_modules/actually-json/typed.d.json.ts (0 errors) ====
|
||||
declare const _default: {};
|
||||
export default _default;
|
||||
|
||||
==== /config.json (0 errors) ====
|
||||
{
|
||||
"version": 1
|
||||
}
|
||||
|
||||
==== /main.mts (5 errors) ====
|
||||
import { oops } from "not.json"; // Ok
|
||||
import moreOops from "actually-json"; // Error
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
|
||||
import typed from "actually-json/typed"; // Error
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
|
||||
|
||||
import config from "./config.json" with { type: "json" }; // Ok
|
||||
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
|
||||
import config2 from "./config.json"; // Error, no attribute
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
|
||||
import { version } from "./config.json" with { type: "json" }; // Error, named import
|
||||
~~~~~~~
|
||||
!!! error TS1544: Named imports from a JSON file into an ECMAScript module are not allowed when 'module' is set to 'NodeNext'.
|
||||
import * as config3 from "./config.json" with { type: "json" };
|
||||
config3.version; // Error
|
||||
~~~~~~~
|
||||
!!! error TS2339: Property 'version' does not exist on type '{ default: { version: number; }; }'.
|
||||
config3.default; // Ok
|
||||
|
||||
==== /loosey.cts (2 errors) ====
|
||||
import config from "./config.json" with { type: "json" }; // Error
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2856: Import attributes are not allowed on statements that compile to CommonJS 'require' calls.
|
||||
import config2 from "./config.json"; // Ok
|
||||
import { version } from "./config.json"; // Ok
|
||||
import * as config3 from "./config.json";
|
||||
config3.version; // Ok
|
||||
config3.default; // Error
|
||||
~~~~~~~
|
||||
!!! error TS2339: Property 'default' does not exist on type '{ version: number; }'.
|
||||
|
||||
79
tests/baselines/reference/nodeModulesJson.symbols
Normal file
79
tests/baselines/reference/nodeModulesJson.symbols
Normal file
@ -0,0 +1,79 @@
|
||||
//// [tests/cases/conformance/node/nodeModulesJson.ts] ////
|
||||
|
||||
=== /node_modules/not.json/index.d.ts ===
|
||||
export function oops(json: string): any;
|
||||
>oops : Symbol(oops, Decl(index.d.ts, 0, 0))
|
||||
>json : Symbol(json, Decl(index.d.ts, 0, 21))
|
||||
|
||||
=== /node_modules/actually-json/index.json ===
|
||||
|
||||
{}
|
||||
|
||||
=== /node_modules/actually-json/typed.d.json.ts ===
|
||||
declare const _default: {};
|
||||
>_default : Symbol(_default, Decl(typed.d.json.ts, 0, 13))
|
||||
|
||||
export default _default;
|
||||
>_default : Symbol(_default, Decl(typed.d.json.ts, 0, 13))
|
||||
|
||||
=== /config.json ===
|
||||
{
|
||||
"version": 1
|
||||
>"version" : Symbol("version", Decl(config.json, 0, 1))
|
||||
}
|
||||
|
||||
=== /main.mts ===
|
||||
import { oops } from "not.json"; // Ok
|
||||
>oops : Symbol(oops, Decl(main.mts, 0, 8))
|
||||
|
||||
import moreOops from "actually-json"; // Error
|
||||
>moreOops : Symbol(moreOops, Decl(main.mts, 1, 6))
|
||||
|
||||
import typed from "actually-json/typed"; // Error
|
||||
>typed : Symbol(typed, Decl(main.mts, 2, 6))
|
||||
|
||||
import config from "./config.json" with { type: "json" }; // Ok
|
||||
>config : Symbol(config, Decl(main.mts, 4, 6))
|
||||
|
||||
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
|
||||
>default : Symbol(config, Decl(config.json, 0, 0))
|
||||
>config1 : Symbol(config1, Decl(main.mts, 5, 8))
|
||||
|
||||
import config2 from "./config.json"; // Error, no attribute
|
||||
>config2 : Symbol(config2, Decl(main.mts, 6, 6))
|
||||
|
||||
import { version } from "./config.json" with { type: "json" }; // Error, named import
|
||||
>version : Symbol(version, Decl(main.mts, 7, 8))
|
||||
|
||||
import * as config3 from "./config.json" with { type: "json" };
|
||||
>config3 : Symbol(config3, Decl(main.mts, 8, 6))
|
||||
|
||||
config3.version; // Error
|
||||
>config3 : Symbol(config3, Decl(main.mts, 8, 6))
|
||||
|
||||
config3.default; // Ok
|
||||
>config3.default : Symbol("/config")
|
||||
>config3 : Symbol(config3, Decl(main.mts, 8, 6))
|
||||
>default : Symbol("/config")
|
||||
|
||||
=== /loosey.cts ===
|
||||
import config from "./config.json" with { type: "json" }; // Error
|
||||
>config : Symbol(config, Decl(loosey.cts, 0, 6))
|
||||
|
||||
import config2 from "./config.json"; // Ok
|
||||
>config2 : Symbol(config2, Decl(loosey.cts, 1, 6))
|
||||
|
||||
import { version } from "./config.json"; // Ok
|
||||
>version : Symbol(version, Decl(loosey.cts, 2, 8))
|
||||
|
||||
import * as config3 from "./config.json";
|
||||
>config3 : Symbol(config3, Decl(loosey.cts, 3, 6))
|
||||
|
||||
config3.version; // Ok
|
||||
>config3.version : Symbol(version, Decl(config.json, 0, 1))
|
||||
>config3 : Symbol(config3, Decl(loosey.cts, 3, 6))
|
||||
>version : Symbol(version, Decl(config.json, 0, 1))
|
||||
|
||||
config3.default; // Error
|
||||
>config3 : Symbol(config3, Decl(loosey.cts, 3, 6))
|
||||
|
||||
129
tests/baselines/reference/nodeModulesJson.types
Normal file
129
tests/baselines/reference/nodeModulesJson.types
Normal file
@ -0,0 +1,129 @@
|
||||
//// [tests/cases/conformance/node/nodeModulesJson.ts] ////
|
||||
|
||||
=== /node_modules/not.json/index.d.ts ===
|
||||
export function oops(json: string): any;
|
||||
>oops : (json: string) => any
|
||||
> : ^ ^^ ^^^^^
|
||||
>json : string
|
||||
> : ^^^^^^
|
||||
|
||||
=== /node_modules/actually-json/index.json ===
|
||||
{}
|
||||
>{} : {}
|
||||
> : ^^
|
||||
|
||||
=== /node_modules/actually-json/typed.d.json.ts ===
|
||||
declare const _default: {};
|
||||
>_default : {}
|
||||
> : ^^
|
||||
|
||||
export default _default;
|
||||
>_default : {}
|
||||
> : ^^
|
||||
|
||||
=== /config.json ===
|
||||
{
|
||||
>{ "version": 1} : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
"version": 1
|
||||
>"version" : number
|
||||
> : ^^^^^^
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
|
||||
=== /main.mts ===
|
||||
import { oops } from "not.json"; // Ok
|
||||
>oops : (json: string) => any
|
||||
> : ^ ^^ ^^^^^
|
||||
|
||||
import moreOops from "actually-json"; // Error
|
||||
>moreOops : {}
|
||||
> : ^^
|
||||
|
||||
import typed from "actually-json/typed"; // Error
|
||||
>typed : typeof typed
|
||||
> : ^^^^^^^^^^^^
|
||||
|
||||
import config from "./config.json" with { type: "json" }; // Ok
|
||||
>config : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
|
||||
>default : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
>config1 : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
import config2 from "./config.json"; // Error, no attribute
|
||||
>config2 : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
import { version } from "./config.json" with { type: "json" }; // Error, named import
|
||||
>version : number
|
||||
> : ^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
import * as config3 from "./config.json" with { type: "json" };
|
||||
>config3 : { default: { version: number; }; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
config3.version; // Error
|
||||
>config3.version : any
|
||||
> : ^^^
|
||||
>config3 : { default: { version: number; }; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>version : any
|
||||
> : ^^^
|
||||
|
||||
config3.default; // Ok
|
||||
>config3.default : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
>config3 : { default: { version: number; }; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>default : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
=== /loosey.cts ===
|
||||
import config from "./config.json" with { type: "json" }; // Error
|
||||
>config : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
import config2 from "./config.json"; // Ok
|
||||
>config2 : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
import { version } from "./config.json"; // Ok
|
||||
>version : number
|
||||
> : ^^^^^^
|
||||
|
||||
import * as config3 from "./config.json";
|
||||
>config3 : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
config3.version; // Ok
|
||||
>config3.version : number
|
||||
> : ^^^^^^
|
||||
>config3 : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
>version : number
|
||||
> : ^^^^^^
|
||||
|
||||
config3.default; // Error
|
||||
>config3.default : any
|
||||
> : ^^^
|
||||
>config3 : { version: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^
|
||||
>default : any
|
||||
> : ^^^
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
index.mts(1,34): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
|
||||
index.mts(3,38): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
|
||||
index.ts(1,34): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
|
||||
index.ts(3,38): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
|
||||
|
||||
|
||||
==== index.ts (2 errors) ====
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
==== index.cts (0 errors) ====
|
||||
import pkg from "./package.json";
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
==== index.mts (2 errors) ====
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
==== package.json (0 errors) ====
|
||||
{
|
||||
"name": "pkg",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"default": "misedirection"
|
||||
}
|
||||
@ -1,21 +1,21 @@
|
||||
//// [tests/cases/conformance/node/nodeModulesResolveJsonModule.ts] ////
|
||||
|
||||
//// [index.ts]
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
//// [index.cts]
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json";
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
//// [index.mts]
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
//// [package.json]
|
||||
@ -34,9 +34,9 @@ export const name2 = ns.default.name;
|
||||
"default": "misedirection"
|
||||
}
|
||||
//// [index.js]
|
||||
import pkg from "./package.json";
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
//// [index.cjs]
|
||||
@ -75,9 +75,9 @@ const ns = __importStar(require("./package.json"));
|
||||
exports.thing = ns;
|
||||
exports.name2 = ns.default.name;
|
||||
//// [index.mjs]
|
||||
import pkg from "./package.json";
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//// [tests/cases/conformance/node/nodeModulesResolveJsonModule.ts] ////
|
||||
|
||||
=== index.ts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
>pkg : Symbol(pkg, Decl(index.ts, 0, 6))
|
||||
|
||||
export const name = pkg.name;
|
||||
@ -10,7 +10,7 @@ export const name = pkg.name;
|
||||
>pkg : Symbol(pkg, Decl(index.ts, 0, 6))
|
||||
>name : Symbol("name", Decl(package.json, 0, 1))
|
||||
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
>ns : Symbol(ns, Decl(index.ts, 2, 6))
|
||||
|
||||
export const thing = ns;
|
||||
@ -26,7 +26,7 @@ export const name2 = ns.default.name;
|
||||
>name : Symbol("name", Decl(package.json, 0, 1))
|
||||
|
||||
=== index.cts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json";
|
||||
>pkg : Symbol(pkg, Decl(index.cts, 0, 6))
|
||||
|
||||
export const name = pkg.name;
|
||||
@ -51,7 +51,7 @@ export const name2 = ns.default.name;
|
||||
>name : Symbol("name", Decl(package.json, 0, 1))
|
||||
|
||||
=== index.mts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
>pkg : Symbol(pkg, Decl(index.mts, 0, 6))
|
||||
|
||||
export const name = pkg.name;
|
||||
@ -60,7 +60,7 @@ export const name = pkg.name;
|
||||
>pkg : Symbol(pkg, Decl(index.mts, 0, 6))
|
||||
>name : Symbol("name", Decl(package.json, 0, 1))
|
||||
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
>ns : Symbol(ns, Decl(index.mts, 2, 6))
|
||||
|
||||
export const thing = ns;
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
//// [tests/cases/conformance/node/nodeModulesResolveJsonModule.ts] ////
|
||||
|
||||
=== index.ts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
>pkg : { name: string; version: string; type: string; default: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
export const name = pkg.name;
|
||||
>name : string
|
||||
@ -15,9 +17,11 @@ export const name = pkg.name;
|
||||
>name : string
|
||||
> : ^^^^^^
|
||||
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
>ns : { default: { name: string; version: string; type: string; default: string; }; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
export const thing = ns;
|
||||
>thing : { default: { name: string; version: string; type: string; default: string; }; }
|
||||
@ -40,7 +44,7 @@ export const name2 = ns.default.name;
|
||||
> : ^^^^^^
|
||||
|
||||
=== index.cts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json";
|
||||
>pkg : { name: string; version: string; type: string; default: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -79,9 +83,11 @@ export const name2 = ns.default.name;
|
||||
> : ^^^^^^
|
||||
|
||||
=== index.mts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
>pkg : { name: string; version: string; type: string; default: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
export const name = pkg.name;
|
||||
>name : string
|
||||
@ -93,9 +99,11 @@ export const name = pkg.name;
|
||||
>name : string
|
||||
> : ^^^^^^
|
||||
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
>ns : { default: { name: string; version: string; type: string; default: string; }; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : any
|
||||
> : ^^^
|
||||
|
||||
export const thing = ns;
|
||||
>thing : { default: { name: string; version: string; type: string; default: string; }; }
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
//// [tests/cases/conformance/node/nodeModulesResolveJsonModule.ts] ////
|
||||
|
||||
//// [index.ts]
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
//// [index.cts]
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json";
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
//// [index.mts]
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
//// [package.json]
|
||||
@ -34,9 +34,9 @@ export const name2 = ns.default.name;
|
||||
"default": "misedirection"
|
||||
}
|
||||
//// [index.js]
|
||||
import pkg from "./package.json";
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
//// [index.cjs]
|
||||
@ -75,9 +75,9 @@ const ns = __importStar(require("./package.json"));
|
||||
exports.thing = ns;
|
||||
exports.name2 = ns.default.name;
|
||||
//// [index.mjs]
|
||||
import pkg from "./package.json";
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//// [tests/cases/conformance/node/nodeModulesResolveJsonModule.ts] ////
|
||||
|
||||
=== index.ts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
>pkg : Symbol(pkg, Decl(index.ts, 0, 6))
|
||||
|
||||
export const name = pkg.name;
|
||||
@ -10,7 +10,7 @@ export const name = pkg.name;
|
||||
>pkg : Symbol(pkg, Decl(index.ts, 0, 6))
|
||||
>name : Symbol("name", Decl(package.json, 0, 1))
|
||||
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
>ns : Symbol(ns, Decl(index.ts, 2, 6))
|
||||
|
||||
export const thing = ns;
|
||||
@ -26,7 +26,7 @@ export const name2 = ns.default.name;
|
||||
>name : Symbol("name", Decl(package.json, 0, 1))
|
||||
|
||||
=== index.cts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json";
|
||||
>pkg : Symbol(pkg, Decl(index.cts, 0, 6))
|
||||
|
||||
export const name = pkg.name;
|
||||
@ -51,7 +51,7 @@ export const name2 = ns.default.name;
|
||||
>name : Symbol("name", Decl(package.json, 0, 1))
|
||||
|
||||
=== index.mts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
>pkg : Symbol(pkg, Decl(index.mts, 0, 6))
|
||||
|
||||
export const name = pkg.name;
|
||||
@ -60,7 +60,7 @@ export const name = pkg.name;
|
||||
>pkg : Symbol(pkg, Decl(index.mts, 0, 6))
|
||||
>name : Symbol("name", Decl(package.json, 0, 1))
|
||||
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
>ns : Symbol(ns, Decl(index.mts, 2, 6))
|
||||
|
||||
export const thing = ns;
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
//// [tests/cases/conformance/node/nodeModulesResolveJsonModule.ts] ////
|
||||
|
||||
=== index.ts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
>pkg : { name: string; version: string; type: string; default: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : error
|
||||
|
||||
export const name = pkg.name;
|
||||
>name : string
|
||||
@ -15,9 +16,10 @@ export const name = pkg.name;
|
||||
>name : string
|
||||
> : ^^^^^^
|
||||
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
>ns : { default: { name: string; version: string; type: string; default: string; }; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : error
|
||||
|
||||
export const thing = ns;
|
||||
>thing : { default: { name: string; version: string; type: string; default: string; }; }
|
||||
@ -40,7 +42,7 @@ export const name2 = ns.default.name;
|
||||
> : ^^^^^^
|
||||
|
||||
=== index.cts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json";
|
||||
>pkg : { name: string; version: string; type: string; default: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -79,9 +81,10 @@ export const name2 = ns.default.name;
|
||||
> : ^^^^^^
|
||||
|
||||
=== index.mts ===
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
>pkg : { name: string; version: string; type: string; default: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : error
|
||||
|
||||
export const name = pkg.name;
|
||||
>name : string
|
||||
@ -93,9 +96,10 @@ export const name = pkg.name;
|
||||
>name : string
|
||||
> : ^^^^^^
|
||||
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
>ns : { default: { name: string; version: string; type: string; default: string; }; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : error
|
||||
|
||||
export const thing = ns;
|
||||
>thing : { default: { name: string; version: string; type: string; default: string; }; }
|
||||
|
||||
58
tests/cases/conformance/node/nodeModulesJson.ts
Normal file
58
tests/cases/conformance/node/nodeModulesJson.ts
Normal file
@ -0,0 +1,58 @@
|
||||
// @module: nodenext
|
||||
// @resolveJsonModule: true
|
||||
// @noEmit: true
|
||||
|
||||
// @Filename: /node_modules/not.json/package.json
|
||||
{
|
||||
"name": "not.json",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"exports": "./index.js"
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/not.json/index.d.ts
|
||||
export function oops(json: string): any;
|
||||
|
||||
// @Filename: /node_modules/actually-json/package.json
|
||||
{
|
||||
"name": "actually-json",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.json",
|
||||
"./typed": "./typed.d.json.ts"
|
||||
}
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/actually-json/index.json
|
||||
{}
|
||||
|
||||
// @Filename: /node_modules/actually-json/typed.d.json.ts
|
||||
declare const _default: {};
|
||||
export default _default;
|
||||
|
||||
// @Filename: /config.json
|
||||
{
|
||||
"version": 1
|
||||
}
|
||||
|
||||
// @Filename: /main.mts
|
||||
import { oops } from "not.json"; // Ok
|
||||
import moreOops from "actually-json"; // Error
|
||||
import typed from "actually-json/typed"; // Error
|
||||
|
||||
import config from "./config.json" with { type: "json" }; // Ok
|
||||
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
|
||||
import config2 from "./config.json"; // Error, no attribute
|
||||
import { version } from "./config.json" with { type: "json" }; // Error, named import
|
||||
import * as config3 from "./config.json" with { type: "json" };
|
||||
config3.version; // Error
|
||||
config3.default; // Ok
|
||||
|
||||
// @Filename: /loosey.cts
|
||||
import config from "./config.json" with { type: "json" }; // Error
|
||||
import config2 from "./config.json"; // Ok
|
||||
import { version } from "./config.json"; // Ok
|
||||
import * as config3 from "./config.json";
|
||||
config3.version; // Ok
|
||||
config3.default; // Error
|
||||
@ -3,21 +3,21 @@
|
||||
// @outDir: ./out
|
||||
// @declaration: true
|
||||
// @filename: index.ts
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
// @filename: index.cts
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json";
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
// @filename: index.mts
|
||||
import pkg from "./package.json"
|
||||
import pkg from "./package.json" with { type: "json" };
|
||||
export const name = pkg.name;
|
||||
import * as ns from "./package.json";
|
||||
import * as ns from "./package.json" with { type: "json" };
|
||||
export const thing = ns;
|
||||
export const name2 = ns.default.name;
|
||||
// @filename: package.json
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user