microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
99.81k stars 12.35k forks source link

[isolatedDeclarations] Should imported JSON files be emitted when "resolveJsonModules", "emitDeclarationOnly", and "isolatedDeclarations" are all enabled? #58684

Open MichaelMitchell-at opened 2 months ago

MichaelMitchell-at commented 2 months ago

🔍 Search Terms

json, resolvejsonmodules, isolateddeclarations, emit, declarations, import, emitDeclarationOnly

✅ Viability Checklist

⭐ Suggestion

Emit/transpile JSON files when the aforementioned compile options are enabled

📃 Motivating Example

The primary purpose of isolated declarations is to be able to emit declarations for a project without needing to typecheck it and one of the main motivators for that is being able to start typechecking downstream projects, e.g. in a composite build, without waiting for typecheck.

It might be fair to say then that it would be good for downstream projects to be able to start typechecking without waiting for their dependees to transpile code. Even with isolated declarations, this is not possible at the moment, because types may depend on JSON files when resolveJsonModules is enabled, and JSON files are only emitted/copied when JS transpilation is enabled, i.e. "emitDeclarationOnly": false.

💻 Use Cases

Being able to typecheck a composite project in parallel where sub-projects are configured with

    "isolatedDeclarations": true,
    "emitDeclarationOnly": true,
    "resolveJsonModule": true,
sheetalkamat commented 2 months ago

I am not sure what we can do here. JSON files are treated like js files with "noDts" emit and hence they are transpileModule output than transpileDeclaration. So i dont think they should be output of that function or should be generated with emitDeclarationOnly.

MichaelMitchell-at commented 2 weeks ago

A workaround we have is to do something like the following:

// @strict: true
// @declaration: true
// @showEmit
// @resolveJsonModule
// @showEmittedFile: index.d.ts

// @filename: data.json
{"x": 42}

// @filename: index.ts
import data from './data.json';
export const typedData = data;

where tsc will emit index.d.ts as

export declare const typedData: {
    x: number;
};

But this is less than ideal when isolatedDeclarations is enabled, since it would require inlining the entirety of the JSON data, which could be large and doubles the amount of code. For now we are just splitting out JSON files with an accompanying TS file wrapper like above into their own TS projects and leaving isolatedDeclarations disabled for those projects.