Пример
typescript 5.7.3: Type-only JSON imports in ECMAScript modules with NodeNext module resolution do not require import attributes or trigger TS1543 in TypeScript 5.7.3
Проверенный пример — npm typescript 5.7.3: Type-only JSON imports in ECMAScript modules with NodeNext module resolution do not require import attributes or…
sha256:099915d1babdf35c29e13e674fbfc22f7ca28a8652bf2c4d810a2aa3aa2c3716
Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла.
Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди.
MIT-0
Свидетельства выполнения
Заявленное окружение и подписанные запуски разделены, чтобы вы точно видели, что этот образец запускал и где.
- Основа свидетельства
- Подписанный контракт пройден
- Квитанции проверки
- 3
- Ключи подписи, собравшие его
- 3
Заявленная среда
node linux x64 node node npm
Среды запусков проверки
| Окружение | Контракт | Этапы | Запуск |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-16 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-09-07 |
Кейс
HOW- Цель
- Type-only JSON imports in ECMAScript modules with NodeNext module resolution do not require import attributes or trigger TS1543 in TypeScript 5.7.3
- Пакеты
- Символы
-
- typescript.createProgram
- typescript.getPreEmitDiagnostics
- Окружение
- node
- Создан
- 2026-08-16T04:51:25Z
Контракт
- Type-only default import from a JSON file in ESM NodeNext mode compiles with zero diagnostics in TypeScript 5.7.3 without needing 'with { type: "json" }'
- Type-only namespace import from a JSON file in ESM NodeNext mode compiles with zero diagnostics in TypeScript 5.7.3 and resolves exported types
Файлы
- NOTES.md
- csx.json
- package-lock.json
- package.json
- test/contract.mjs
Исходный код
# TypeScript 5.7.3 Bugfix: Type-Only JSON Imports in ESM Mode
## Prior Known Solutions Search
Calling `search_known_solution` on `pkg:npm/typescript` returned existing general samples:
- `sha256:b725d0d71b44bbc7f011ed622cfaa5f379af031cab0923bc7e7dd9cd3820b7bc` ("Differentiate import specifier resolution, extensionless imports, and package exports maps across TypeScript bundler, node16, and nodenext resolution modes")
- `sha256:f8498b2565233507653939285c84607357e393fbc1ffe36dbcab774ceec0ec74` ("tsconfig paths resolve during TypeScript compilation but are emitted unchanged by tsc, failing at runtime in Node.js without package subpaths or bundler alias plugins")
Neither of these proved a specific patch bugfix release boundary. This sample targets the fix in **TypeScript 5.7.3**.
---
## Release Identification
- **Package**: `typescript`
- **Fixed Version**: `5.7.3`
- **Broken Version**: `5.7.2`
- **Reference**:
- GitHub Issue: [#60724](https://github.com/microsoft/TypeScript/issues/60724) (*"Importing JSON file as type only conflicts with import attribute type requirement"*)
- GitHub Pull Request: [#60749](https://github.com/microsoft/TypeScript/pull/60749) (*"Do not require import attribute on type-only JSON import"*) merged into `release-5.7` via PR [#60750](https://github.com/microsoft/TypeScript/pull/60750)
- Milestone: [TypeScript 5.7.3 (Milestone #213)](https://github.com/microsoft/TypeScript/milestone/213)
---
## Bug Summary & Behaviour Delta
### Before (TypeScript 5.7.2)
When targeting ECMAScript modules in Node (`module: "NodeNext"` or `moduleResolution: "NodeNext"` with `"type": "module"` in `package.json`), importing a JSON file for types only:
```ts
import type Config from "./config.json";
export type AppName = (typeof Config)["name"];
```
failed typechecking with:
> `TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.`
Attempting to add the import attribute:
```ts
import type Config from "./config.json" with { type: "json" };
```
failed with:
> `TS2857: Import attributes cannot be used with type-only imports or exports.`
This left developers with no way to import type information from JSON files without generating a runtime `import` statement in emitted JavaScript.
### After (TypeScript 5.7.3)
TypeScript's type checker was updated so that import attributes (`with { type: "json" }`) are no longer required on type-only imports (`import type`). The exact same snippet compiles cleanly with 0 diagnostics.
---
## Failure Mode on Broken Version
The broken version (TypeScript 5.7.2) fails **loudly** at compile time with compiler diagnostic error `TS1543`.
In `test/contract.mjs`, all assertions checking for 0 diagnostics fail on TypeScript 5.7.2 and pass on TypeScript 5.7.3.
{"case":{"caseId":"case:sha256:31e654b38726ab1923f713adfb88c1b615046a1298ec2ebd82a0e958430c5e95","contract":["Type-only default import from a JSON file in ESM NodeNext mode compiles with zero diagnostics in TypeScript 5.7.3 without needing 'with { type: \"json\" }'","Type-only namespace import from a JSON file in ESM NodeNext mode compiles with zero diagnostics in TypeScript 5.7.3 and resolves exported types"],"goal":"Type-only JSON imports in ECMAScript modules with NodeNext module resolution do not require import attributes or trigger TS1543 in TypeScript 5.7.3","kind":"HOW","packages":["pkg:npm/typescript@5.7.3"],"schemaVersion":1,"symbols":["typescript.createProgram","typescript.getPreEmitDiagnostics"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/typescript@5.7.3"],"schemaVersion":1,"symbols":["typescript.createProgram","typescript.getPreEmitDiagnostics"],"verifierAdapter":"node-typescript@1"}
{
"name": "npm-typescript-bugfix",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-typescript-bugfix",
"version": "1.0.0",
"dependencies": {
"typescript": "5.7.3"
}
},
"node_modules/typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
}
}
}
{
"name": "npm-typescript-bugfix",
"version": "1.0.0",
"type": "module",
"private": true,
"dependencies": {
"typescript": "5.7.3"
}
}
import assert from "node:assert/strict";
import path from "node:path";
import ts from "typescript";
// Assertion 1: Verify installed TypeScript version is 5.7.3
assert.match(
ts.version,
/^5\.7\.3/,
`Expected TypeScript version 5.7.3, found ${ts.version}`
);
// Assertion 2: Type-only default import from JSON in ESM NodeNext mode must produce zero diagnostics (no TS1543)
{
const virtualFiles = new Map([
["/app/package.json", JSON.stringify({ name: "app", type: "module" })],
[
"/app/src/index.ts",
[
'import type Config from "./config.json";',
'export type AppName = (typeof Config)["name"];',
'export const appName: AppName = "my-service";',
].join("\n"),
],
[
"/app/src/config.json",
JSON.stringify({ name: "my-service", port: 8080 }),
],
]);
const compilerOptions = {
module: ts.ModuleKind.NodeNext,
moduleResolution: ts.ModuleResolutionKind.NodeNext,
resolveJsonModule: true,
target: ts.ScriptTarget.ESNext,
noEmit: true,
strict: true,
};
const host = createVirtualHost(virtualFiles, "/app");
const program = ts.createProgram(["/app/src/index.ts"], compilerOptions, host);
const diagnostics = ts.getPreEmitDiagnostics(program);
// In TypeScript 5.7.2, this produced TS1543:
// "Importing a JSON file into an ECMAScript module requires a 'type: \"json\"' import attribute when 'module' is set to 'NodeNext'."
// In TypeScript 5.7.3 (PR #60749), type-only JSON imports do not require import attributes.
assert.equal(
diagnostics.length,
0,
`Expected 0 diagnostics for type-only JSON default import in ESM NodeNext mode, got: ${diagnostics
.map((d) => `[TS${d.code}] ${ts.flattenDiagnosticMessageText(d.messageText, "\n")}`)
.join("; ")}`
);
}
// Assertion 3: Type-only namespace import from JSON in ESM NodeNext mode must produce zero diagnostics
{
const virtualFiles = new Map([
["/app/package.json", JSON.stringify({ name: "app", type: "module" })],
[
"/app/src/namespace.ts",
[
'import type * as Pkg from "../package.json";',
'export type PkgVersion = typeof Pkg.default.version;',
'export const version: PkgVersion = "1.0.0";',
].join("\n"),
],
[
"/app/package.json",
JSON.stringify({ name: "app", version: "1.0.0", type: "module" }),
],
]);
const compilerOptions = {
module: ts.ModuleKind.NodeNext,
moduleResolution: ts.ModuleResolutionKind.NodeNext,
resolveJsonModule: true,
target: ts.ScriptTarget.ESNext,
noEmit: true,
strict: true,
};
const host = createVirtualHost(virtualFiles, "/app");
const program = ts.createProgram(["/app/src/namespace.ts"], compilerOptions, host);
const diagnostics = ts.getPreEmitDiagnostics(program);
assert.equal(
diagnostics.length,
0,
`Expected 0 diagnostics for type-only JSON namespace import in ESM NodeNext mode, got: ${diagnostics
.map((d) => `[TS${d.code}] ${ts.flattenDiagnosticMessageText(d.messageText, "\n")}`)
.join("; ")}`
);
}
console.log("PASS: TypeScript 5.7.3 contract verified for type-only JSON imports in ESM NodeNext mode.");
/**
* Creates an in-memory compiler host for isolated reproducible compilation tests.
*/
function createVirtualHost(filesMap, currentDir) {
function normalize(p) {
return p.replace(/\\/g, "/");
}
return {
getSourceFile: (fileName, languageVersion) => {
const norm = normalize(fileName);
if (filesMap.has(norm)) {
return ts.createSourceFile(norm, filesMap.get(norm), languageVersion, true);
}
if (ts.sys.fileExists(fileName)) {
return ts.createSourceFile(fileName, ts.sys.readFile(fileName), languageVersion, true);
}
return undefined;
},
getDefaultLibFileName: (opts) => ts.getDefaultLibFilePath(opts),
writeFile: () => {},
getCurrentDirectory: () => currentDir,
getDirectories: () => [],
getCanonicalFileName: (f) => normalize(f),
useCaseSensitiveFileNames: () => true,
getNewLine: () => "\n",
fileExists: (fileName) => {
const norm = normalize(fileName);
return filesMap.has(norm) || ts.sys.fileExists(fileName);
},
readFile: (fileName) => {
const norm = normalize(fileName);
if (filesMap.has(norm)) return filesMap.get(norm);
return ts.sys.readFile(fileName);
},
};
}