microsoft / TypeScript

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

Allow tsconfig.yaml in addition to tsconfig.json #40027

Open dradetsky opened 4 years ago

dradetsky commented 4 years ago

Search Terms

yaml tsconfig format

Suggestion

I suggest allowing the tsconfig.json file to be replaced with tsconfig.yaml.

This would be implemented by simply converting the yaml to json and passing it to whatever method currently interprets the contents of tsconfig.json.

Additionally, I would propose that the presence of both a tsconfig.json and a tsconfig.yaml file in the root of a project is an error.

Use Cases

Like #30400 (which I found originally), I'd like to add comments to my project config. Also, yaml is just a nicer format for something intended to be edited by a human.

I have created this simply because #30400 (which called for adding tsconfig.js) was closed for reasons which do not apply to yaml. So I thought there should be an open issue. You can always close it for other reasons, right?

Examples

following the example in the handbook

% cat example.json
{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": true,
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true
  },
  "files": [
    "core.ts",
    "sys.ts",
    "types.ts",
    "scanner.ts",
    "parser.ts",
    "utilities.ts",
    "binder.ts",
    "checker.ts",
    "emitter.ts",
    "program.ts",
    "commandLineParser.ts",
    "tsc.ts",
    "diagnosticInformationMap.generated.ts"
  ]
}
% cat example.yaml
compilerOptions:
  module: commonjs
  noImplicitAny: true
  removeComments: true
  preserveConstEnums: true
  sourceMap: true
files:
  - core.ts
  - sys.ts
  - types.ts
  - scanner.ts
  - parser.ts
  - utilities.ts
  - binder.ts
  - checker.ts
  - emitter.ts
  - program.ts
  - commandLineParser.ts
  - tsc.ts
  - diagnosticInformationMap.generated.ts

Checklist

I'M PRETTY SURE My suggestion meets these guidelines:

dradetsky commented 4 years ago

Additionally, addressing the question of "What shortcomings exist with current approaches?"

I did note that it was possible to add comments to the tsconfig.json. However, from a human-interface perspective, this is bad. People who know how JSON works know that it doesn't generally support comments. So they won't try to add comments to this file even if they want to. And people who don't yet know how JSON works will see examples and try to put comments in their package.json files and find that it doesn't work and be confused.

Also, maintaining a JSON parser which supports comments is work which is probably better avoided (although I recognize that dropping support for comments in tsconfig.json may not be feasible). If you want to comment your config file, you can just use YAML. You don't need to add one more unnamed, unstandardized way of having JSON-but-with-comments. I mean, now that you have you probably have to support it for some time, but pushing the existing userbase towards doing this by just using YAML would probably be a good thing.

dradetsky commented 4 years ago

@RyanCavanaugh is there a standard for "Received Enough Feedback" or is it just basically "Core devs feel that number of positive respondents is sufficient given the (expected) complexity of the change?"

I would note that @alexmiddeleer arguably counts as a positive respondent.

EfstathiadisD commented 4 years ago

Please implement this. JSON is not a proper format, for configuration. See eslint and prettier. They both accept yaml formats. If Typescript accepted that, it would be a huge step forward. JSON, should never be the default configuration otpion. It is one more bad habit, that came from node.

RyanCavanaugh commented 4 years ago

is there a standard for "Received Enough Feedback" or is it just basically "Core devs feel that number of positive respondents is sufficient given the (expected) complexity of the change?"

There's no concrete standard. The number of positive respondents is one factor, but we're also considering the qualitative aspects of the verbatim comments -- e.g., are people completely blocked, are they inconvenienced, are they feeling a sense of technical friction, are they resorting to difficult workarounds, etc..

dradetsky commented 3 years ago

@RyanCavanaugh checking in. How are core typescript devs currently feeling about the level of feedback so far?

montyz commented 3 years ago

Yaml for allowing comments would make my life easier, and help my coworkers too.

RyanCavanaugh commented 3 years ago

Yaml for allowing comments would make my life easier

Just so you know, you can already write comments in tsconfig.json files

dradetsky commented 3 years ago

@RyanCavanaugh isn't explaining that to people over and over fun?

RyanCavanaugh commented 3 years ago

It pays the bills 🙃

jcayzac commented 3 years ago

YAML is a better configuration format than JSON for the same reasons JSON is better than XML: by forcing humans to read noisy input, mistakes are more easily made; by forcing humans to decorate content with extra syntax, copy-paste happens more often and mistakes are more easily made.

sequencerr commented 3 years ago

YAML syntax is prettier for me. Hope this will be realized.

jcayzac commented 3 years ago

By the way, I think it's pretty obvious to anybody who has seriously worked with YAML, but maybe it's useful to state that it's YAML 1.2 that should be supported, not the legacy, ambiguous, error-prone YAML 1.1 spec.

kaaax0815 commented 3 years ago

Is this in development? Because I think it would be a great addition

jacobq commented 2 years ago

FWIW, I use tsc to generate JS for node using native ESM (no babel, no webpack, etc.), and in order to get module path mapping to work I rely on being able to read tsconfig.json (in a custom loader) via the simple JSON.parse('tsconfig.json').

While I like YAML, I also like keeping things simple. If we have to support more formats then anything reading content from tsconfig is going to need another layer of abstraction / more code. It wouldn't be a big deal if YAML parse/stringify functions were built into the standard (ES20xx), but presently they are not, so this would likely mean adding yet another library to devDependencies. If tsconfig can be specified via multiple languages/formats then it should really provide its own type/interface and some kind of parseTsConfig() function, but I think that's making things more complex than they need to be. If you really want to use YAML, why not just add a step to the build that generates a JSON from the YAML? (e.g. https://www.npmjs.com/package/yamljs#command-line-tools)

ChrisCrossCrash commented 2 years ago

@jacobq Thanks for the yamljs recommendation.

Here's how I used it:

  1. npm install --save-dev yamljs to install the yaml-to-json converter.
  2. json2yaml tsconfig.json > tsconfig.yaml to convert the existing TS configuration to yaml (this is a one-time step).
  3. I've modified my package.json with the following changes:
    {
    "scripts": {
    "build-configs": "yaml2json . --pretty --save",
    "develop": "npm run build-configs && gatsby develop"
    }
    }

    build-configs converts all the .yaml files in my root project directory into .json files. I've done it this way so that it also converts my other configs. For example: cypress.yaml also gets converted to cypress.json

Now I can edit the tsconfig.yaml, and it automatically gets converted to tsconfig.json when I execute npm run develop.

Pros

Cons

For me, the cons outweigh the pros. The deal-breaker for me was how my IDE doesn't give me hints in my non-tsconfig.yaml config files.

jacobq commented 2 years ago

Sorry if this comment is veering off-topic, but I appreciated your (@ChrisCrossCrash) thorough note taking for other interested parties so wanted to respond to your question.

  • At least in my IDE (PyCharm Professional), code hinting works on the tsconfig.yaml file. I can hover over the config keys and PyCharm gives me popup descriptions (see image below). Auto-completion also works. Unfortunately, the same cannot be said for my only other config, cypress.yaml. PyCharm doesn't give hints like it does in cypress.json (If somebody knows how to fix this, please let me know).

These hints (hover, auto-completion, highlighting, and whatnot) are generally made possible via JSON Schema definitions mapped to those files. IIRC, JetBrains IDEs uses the public schemastore.org catalog; see https://www.jetbrains.com/help/pycharm/json.html#ws_json_using_schemas & https://brunopaz.dev/blog/how-to-create-your-own-auto-completion-for-json-and-yaml-files-on-vs-code-with-the-help-of-json-schema

  • New dev dependency yamljs in my project
  • Having two config files is confusing for people who aren't familiar with your project. You can't even add a comment to the top of the json file saying // don't edit this. Edit tsconfig.yaml instead, since json doesn't support comments, and even if it did, it would be overwritten.
  • This adds a bit of weird complexity to the project in order to do something pretty trivial.

I would argue that this complexity is the cost of the feature. It can either be put into your projects (annoying/inelegant) or upstream (still inelegant but no longer so annoying due to being practically invisible), but in any case it must exist somewhere. More choices (JSON/YAML/TOML/INI/XML/fill-in-the-blank) + more human-friendliness is nice but not free.

Another solution path to consider would be to make an "add-on" module/lib/tool that contains this functionality and can be dropped into your projects -- keeping the functionality isolated without bloating the core upstream package. How that's done depends a lot on your specific project/build arrangement, of course. One way would be to make a @my-scope/typescript package that basically "replaces" typescript in your projects but passes everything through to it except first does YAML->JSON (and perhaps keeps that JSON file out of sight / version control or deletes it after compilation). It might even make sense to do this as an IDE plugin instead.

If the core team believes that the value of adding a feature like this is worth the cost (effort, maintenance, doc, support, ...) that's all fine and good. In my experience, though, I set up tsconfig.json for a project then practically forget that it's even there as I get busy developing the app itself, so I personally wouldn't want to spend my time working on it.

jcayzac commented 2 years ago

While I like YAML, I also like keeping things simple. If we have to support more formats then anything reading content from tsconfig is going to need another layer of abstraction / more code.

This is typically something that should be abstracted for you by an import.meta.

morganbarrett commented 2 years ago

fact: most devs have ocd solution: .typescriptrc.{json|ya?ml}

but yeah, I would love to be able to use yaml for tsconfig

benedictjohannes commented 2 years ago

@RyanCavanaugh I would offer my technical reasoning for why allowing the easier to read and write YAML is a logically sound.

Firstly, every programming language that I know does not support the commented JSON format. Not even nodeJS, try this: let tsConfig = require('tsconfig.json').
Importing a package to parse it might, but why maintain the same file extension and cause confusion?

It pays the bills :upside_down_face:

So does paying someone to compare documents, but I believe there's a great reason Microsoft created the "track changes" feature in Microsoft Word.

Secondly, in defense of NPM (and other package managers) using package.json and not supporting any other is quite obvious: npm needs to be able to (programmatically) alter the contents of package.json.
ESLint, Prettier, Webpack expect the config files to be hand-written, and does not offer to alter the configs in any way. There's no such prettier --alter-config --enable-pragma afterall.
But, there's no tsc --alter-config --set-jsx react to be seen either. So, apart of the effort needed, any reason for sticking with only tsconfig.json?

I'm quite sure the community would be happy to help with PR that helps in the effort part, as long as it won't be rejected for reasons other than it doesn't work or breaks something.

NatoBoram commented 2 years ago

Additionally, putting comments in .json files, while supported it's by some specs-breaking programs, might work sometimes, it's factually wrong. The file should've been .jsonc in the first place so that it's understood by every editor and .json readers and displays as a .jsonc file instead of having to hard-code or configure the tsconfig.json files as being .jsonc files.

image

While Microsoft have already taken the stance in the past that they don't care about this issue, I think it would be better if a .yaml file was used so at least it would be not implementation-dependent and actually respect at least one standard.

The problem this issue addresses is that tsconfig.json does not respect any standards at all. It's a .jsonc file with a .json extension, which breaks every non-Microsoft products because people outside of Microsoft have standards.

gotjoshua commented 2 years ago

I hope that it is clear that this issue is not only about the comments. Also it is a request to also support y?aml files, not to require them instead of json.

There is significant precedence as noted above (eslint and prettier)

Furthermore

Vite also directly supports TS config files. You can use vite.config.ts with the defineConfig helper as well.

which, quite frankly, could be seen as embarrassing that typescript itself doesn't.

woutermont commented 1 year ago

I'll bump this once more, because it would really improve developer experience when we'd be able to write TS config in YAML ❤️

cobaltp commented 1 year ago

I totally agree with this. Except for this one, all of my other settings file are written in yaml. It's more clear and human readable.

matthewjh commented 1 year ago

Yes please. Since moving to PNPM, we switched from package.json to package.yaml for improved readability and ergonomics (including, but not limited to comments). Would love to do the same for our tsconfigs.

bennidi commented 11 months ago

Just to add another argument in favor of yaml: The configuration of typescript in combination with the other parts of tooling like babel, metro, vite, webpack etc. is horribly complex and confusing. This is a VERY BIG DOWNSIDE of the freedom of the whole JS centred ecosystem. Every tool evolves independently and the more successful ones become kind of standard (without proper process of standarization).

As a developer I have spent countless hours trying to figure out the correct configuration for my toolstack. A very painful process. One reason for this being so difficult is because developers can not put comments in JSON and as such can not embed the contextual information that is actually the reason for a certain config option to be set this way or another. Period! It is freaking annoying and a painful limitation and drawback of JSON format when used for actual coding (not just data).

I think that support yaml as format for tsconfig would mean a very big improvement to the future of the TS ecosystem. It is also a relatively low handing fruit because YAML parsers are available and it is just syntax and not semantics that will be added. It is also backward compatible because YAML will be added and not used to replace JSON.

So, actually...why the resistance to ship this change?

jasongitmail commented 11 months ago

Would rather see ts.config.js to go alongside the new eslint.config.js+ prettier.config.js, playwright.config.js, vite.config.js, tailwind.config.js, etc. Omg, so many. But really, can import from a global config using ES6, comments, consistency... 😝

cdaringe commented 7 months ago

I support something like this request, purely on the merits of the following observation for tsconfig:

JSON != JSONC

https://code.visualstudio.com/docs/languages/json#_json-with-comments

I have zero qualms with JSON. However, labeling a file as JSON immediately invokes expectations of its content.

I have been using tsconfig.json happily for years without issue.

Today, this naming misnomer caused a demonstrably competent, smart, senior engineer to make a smart, but incorrect assumption. A formatter update started appending commas to final items in arrays in our tsconfig. "That's not valid JSON" they noticed, which prompted a bunch of activity to protect our automated builds/release pipelines... which was all not necessary, because of course, tsconfig.json is not json. I've observed peer developers on more than one occasion try and read/parse tsconfig.json with JSON.parse, etc unsuccessfully.

By marking a non-json file as json, developer friction has observably ensued. It's not a huge deal, but it's completely avoidable for an enormous population of users.

Dropping tsconfig.json support is a non-starter (I presume all parties are aligned there). Going forward, however, I advocate the default config file extension should be honest about its format.

tsconfig.jsonc or tsconfig.yml would be be better defaults, as there is no ambiguity.

HolgerJeromin commented 7 months ago

Many web tools use yml, but this is perhaps not the best format. https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell