microsoft / TypeScript

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

json files should be usable in .d.ts files without breaking things #24744

Open jpike88 opened 6 years ago

jpike88 commented 6 years ago

Search Terms

resolveJsonModule import definition

Suggestion

As a .json file is a static resource, it should be able to be referenced in a global.d.ts file for example without that file being automatically treated as a module. The reason for this is that a .json file may be used to simply enforce valid translation keys, and you shouldn't need to suck the whole .json file into the transpilation process to do that.

Use Cases

Example:

import translations from "../assets/translations/en-AU.json"
type $translate = {
    instant: (translationKey: keyof typeof translations) => string,
    use: Function,
    proposedLanguage: Function
}

The downside of the current method again is that the translations file is output in the transpilation process, which is wasteful if the file is large.

What the above code snippet is trying to achieve, should be allowed in a .d.ts file without breaking global declaration functionality.

Checklist

My suggestion meets these guidelines:

vekexasia commented 6 years ago

Unfortunately I've the very same issue on a project of mine where the json is imported into the "dist" folder breaking seveal things.

AlCalzone commented 5 years ago

I just ran into the same issue. Given the following directory structure:

build/  - The compiler output ends up here
src/    - The sources reside here
  file1.ts
  file2.ts
  ... and so on
somejsonfile.json - The file I'm trying to include. It is guaranteed to be there in the final module

Compiling the source code results in this structure if I don't reference somejsonfile.json from source code:

build/  - The compiler output ends up here
  file1.js
  file1.d.ts
  ... and so on
src/    - The sources reside here
  file1.ts
  file2.ts
  ... and so on
somejsonfile.json - The file I'm trying to include. It is guaranteed to be there in the final module

If I do import from somejsonfile.json, instead of just compiling from src to build, the structure is shifted:

build/  - The compiler output ends up here
  src/  - This is extraneous!
    file1.js
    file1.d.ts
    ... and so on
  somejsonfile.json  - This is just copied from the root dir.
src/    - The sources reside here
  file1.ts
  file2.ts
  ... and so on
somejsonfile.json

which results in duplication of the json file and an unnecessary src directory inside build.

Unfortunately, this means that resolveJsonModule is unusable for what I'm trying to do - that is reading strongly typed config data from a json file.

@mhegazy Is this the kind of feedback you're looking for?

oryandunn commented 5 years ago

I just ran into this same issue myself.

As @AlCalzone shows above, when importing a json and using the resolveJsonModule flag in your tsconfig.json, tsc will copy that json into the build directory. If you're using the "outDir": "./build" and "rootDir": "./src" options, you will also get an error:

error TS6059: File '.../somejsonfile.json' is not under 'rootDir' '.../src'. 'rootDir' is expected to contain all source files.

It's quite strange because it issues an error, but then carries on with the build, implicitly setting rootDir up level(s) until it finds a common root (in this example, it's up one level).

I've attempted to skirt this issue by setting the include property in tsconfig.json:

"include" : [
    "src/**/*"
]

or by exclude:

"exclude": [
    "somejsonfile.json"
]

or by both

"include": [
    "src/**/*"
],
"exclude": [
    "somejsonfile.json"
]

but in all cases, I get the TS6059 error and end up with the build directory containing a src folder and the somejsonfile.json file.

As of now, I've had to revert to using const jsondata = require("somejsonfile.json");. I'd like to be able to use resolveJsonModule and import, but as of now I'm unable to.

AlCalzone commented 5 years ago

As of now, I've had to revert to using const jsondata = require("somejsonfile.json");. I'd like to be able to use resolveJsonModule and import, but as of now I'm unable to.

I actually only want to use a type that is derived from the contents of the json file, not the contents of the file itself. I feel there should be a way to rely on json files without including them in the build output.

AlCalzone commented 5 years ago

Over the weekend I ran into another issue, where having type checking based on the types from a json config file would have saved me some headaches.

A numeric variable was incorrectly set as a string in the web frontend while the backend was expecting a number. Both have access to the json file at compile time.

AlCalzone commented 5 years ago

My current workaround to get static typechecking based on json contents without file duplication:

  1. Have a symlink from the source directory to the json file in question
  2. Import the symlinked json file in the (.d).ts files.
  3. Delete the json file from the build output in the postbuild step.

This works for me, but I refuse to believe this feature is working as intended.

Edit: checking out a repo with symlinks is problematic on windows though... So the current workaround is just using the json file where it resides and a postbuild step:

"postbuild": "cpx build/src/**/*.* build && rimraf build/src && rimraf build/config.json",
noel-schenk commented 5 years ago

How about another parameter. "compileJsonModule":true|false Current code would still work and for future implementations devs would have the option to keep the strucutre.

Bessonov commented 4 years ago

Have simillar issue:

import program from 'commander'
import { version } from '../package.json'

program
    .version(version)
    .parse(process.argv)
error TS6059: File '/home/vagrant/workspace/package.json' is not under 'rootDir' '/home/vagrant/workspace/src'. 'rootDir' is expected to contain all source files.
CMCDragonkai commented 2 years ago

I find it interesting that even if TS2732 error occurs, the tsc compiler just continues. Surely there must be a way to make it not bother compiling the JSON file, so that we can reference things outside the outDir.