microsoft / TypeScript

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

tsc --init-basic #46150

Open benwainwright opened 3 years ago

benwainwright commented 3 years ago

Suggestion

As a professional TypeScript developer, I start new TS projects all the time. I use tsc --init sometimes, but more often than not I copy tsconfig.json files from other projects because I find the tsconfig.json file that is generated to be horribly spammy.

Having a tsc --init command is valuable to me, because quite often I want to bootstrap a project quickly, but the comments get in my way, as they make it harder to read what the actual config of a project is, and generally look really messy. If I ever run tsc --init the first thing I do is strip out these comments.

I'd really appreciate a tsc --init-basic (or something like it) that provides the same basic configuration set but without any comments.

🔍 Search Terms

tsconfig comments init

✅ Viability Checklist

My suggestion meets these guidelines:

benwainwright commented 3 years ago

I've now forked the repo and worked out how to make this change. I appreciate the issue is still to be accepted; if not, no worries, I'll consider a useful exercise in introducing myself to a codebase I'd like to contribute in.

If you believe this feature has enough value for my contribution to be included, the remaining guidance I need in order to finish my patch are on these areas:

fatcerberus commented 3 years ago

At least one test should fail in the absence of your non-test code changes

I think this is just a fancy way of saying “If you make a code change, you should write (or modify) one or more tests for it, and at least one of the new tests must fail without your change.”

It doesn’t mean your change has to cause existing tests to fail, although of course it may, in which case that has to be dealt with too.

andrewbranch commented 3 years ago

FWIW I’ve always wanted this feature, but I’m not confident that a PR would get accepted and I would hate to see you burned by infinite bikeshedding as a first time contributor. If this feature is your passion, don’t let me stop you from implementing it, but be prepared that a PR for an “awaiting more feedback” issue may or may not ever get a proper review. If you are just looking to start contributing to TS anywhere, I would encourage you to search for “help wanted” and “good first issue” labels, where you’re much more likely to get support with a PR from start to finish.

benwainwright commented 3 years ago

I would hate to see you burned by infinite bikeshedding as a first time contributor. If this feature is your passion, don’t let me stop you from implementing it, but be prepared that a PR for an “awaiting more feedback” issue may or may not ever get a proper review

I mean passion is a strong way of putting it. I believe this change is a no brainer given the ratio of effort to value... but if the PR isn't accepted I'll live as I can just continue copying from my other projects 🤷🏻‍♂️ . From a personal point of view it was a useful excuse to check out the code and understand how to make changes in tsc without having to do too much thinking.

benwainwright commented 3 years ago

If you are just looking to start contributing to TS anywhere, I would encourage you to search for “help wanted” and “good first issue” labels, where you’re much more likely to get support with a PR from start to finish.

I'm aware of this and have started digging through these tickets. But I've not yet found anything which I thought was suitable for my very limited understanding of the codebase yet (and wasn't already 'claimed'). This is a use case I fully understand (because it's for me) and the implementation is very accessible.

andrewbranch commented 3 years ago

Well, maybe to get some momentum one way or another: @MartinJohns, why are you not a fan?

MartinJohns commented 3 years ago

@andrewbranch I'm generally opposing any new flags or options that bring no real benefit, and I'd say this flag brings no real benefit. It adds bloat (code and feature wise) and is just another option to do the same thing, causing slight fragmentation. Also there's a possible risk of those two init configs diverging, although I believe the code already is smarter than that and the file(s) would be / is generated dynamically.

If a lot of people consider this a value worth adding, I'd say go ahead. But for a few individual cases there are plenty of alternative options (e.g. extending config from npm package, copy existing file, have a local command that generates the file), although these would have to be maintained to make use of new flags in newer versions.

I can see the appeal, but my gut feeling towards such features is a no.

andrewbranch commented 3 years ago

I think I create (and edit) more tsconfigs than the average person since a big part of my job is creating repros of bugs. I agree this isn’t a big value add, but if it existed, I would definitely use it and it would make me happy. On the other hand, I would personally not care about this at all if VS Code had a “strip all comments” command built in, as that would be just as fast for my workflow.

benwainwright commented 3 years ago

@MartinJohns

Also there's a possible risk of those two init configs diverging, although I believe the code already is smarter than that and the file(s) would be / is generated dynamically.

For the record, since I've already implemented the change on a fork, I can tell you that the file is indeed generated dynamically and because of the way it is done, there is no risk of divergence.

and I'd say this flag brings no real benefit

I mean that's a matter of opinion I guess, but I do appreciate that there are other options.

@andrewbranch

On the other hand, I would personally not care about this at all if VS Code had a “strip all comments” command built in, as that would be just as fast for my workflow.

To be honest, I'm a vim user (yeah, sorry - one of those people 😉) and when you put it like that - it will probably take me about 20 minutes to write a vim mapping to do this. It just hadn't occurred to me that anyone would argue against this to be honest, since I've not yet worked with anyone who finds these kind of comments in config files useful at all, and plenty who find them annoying. I'd actually be very much in favour of just removing them outright, but I suspect that would be an even harder sell...

orta commented 3 years ago

I think I'd probably argue against this personally - especially given that @tsconfig/bases exists and at this point has a base for a lot of common JS projects.

I'd think I'd be open to tsc --init --extends which for example:

yarn tsc --init --extends @tsconfig/node14
Created a new tsconfig.json with:

  extends: @tsconfig/node14

You can learn more at https://aka.ms/tsconfig.json

cat tsconfig.json
{
    "extends": "@tsconfig/node14"
    "compilerOptions": {
      /* Visit https://aka.ms/tsconfig.json to read more about this file */
    }
}

This doesn't introduce a new concept to teach (e.g. there's new one flag which only works with --init) but instead extends the idea of 'you can set your own custom tsconfig options from the CLI' to also include extends.

MartinJohns commented 3 years ago

if VS Code had a “strip all comments” command built in, as that would be just as fast for my workflow.

@andrewbranch Well, technically VS Code has such a feature... Kind of, using "Replace" and a Regular Expression.

image image

I quickly hacked together the Regular Expression I used and it's not the prettiest, but it works:
(\n\s+/\*.*(?!\*/))|(\n\s+//[^\n]*)|(\s+/\*.*(?!\*/))

fatcerberus commented 3 years ago

I quickly hacked together the Regular Expression I used and it's not the prettiest, but it works

ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚​N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ

🚎

benwainwright commented 3 years ago

I think I'd probably argue against this personally - especially given that @tsconfig/bases exists and at this point has a base for a lot of common JS projects.

I'd think I'd be open to tsc --init --extends which for example:

yarn tsc --init --extends @tsconfig/node14
Created a new tsconfig.json with:

  extends: @tsconfig/node14

You can learn more at https://aka.ms/tsconfig.json

cat tsconfig.json
{
    "extends": "@tsconfig/node14"
    "compilerOptions": {
      /* Visit https://aka.ms/tsconfig.json to read more about this file */
    }
}

This doesn't introduce a new concept to teach (e.g. there's new one flag which only works with --init) but instead extends the idea of 'you can set your own custom tsconfig options from the CLI' to also include extends.

@orta that's actually a great idea. What do you think the likelihood of me getting that in if I were to have a go at implementing it?

cdaringe commented 2 years ago

yarn tsc --init --extends @tsconfig/node14

i skim read the above post, got super stoked, and was so disappointed that it wasn't real! 😉

i create a new TS project MAX 1x/day, MIN 3x/week. ya, the flag in question is frivolous at large, but clearly of value enough s.t. ...hey.. here we all are talkin' about it 😄

On the --extends flag idea, I often wouldn't want to install @tsconfig/nodeXY, just use that as my base.

$ tsc --init --base npm:@tsconfig/node17
Downloading npmjs.org/@tsconfig/node14@latest

Created a new tsconfig.json with:                                                                                       

  target: es2020
  module: commonjs
  strict: true
  esModuleInterop: true
  skipLibCheck: false
  strict: true

You can learn more at https://aka.ms/tsconfig.json
yukulele commented 1 year ago

I think tsc --init should always create a tsconfig.json file without comments :

Eventually an option (like --init-all) could allow to generate a tsconfig.json file with all possible options, not commented, with their default values.

xgqfrms commented 1 year ago

Enhance tsc cli

# all config version
$ tsc --init -a
$ tsc --init --all

# mininal config version (default 🚀 )
$ tsc --init

https://github.com/microsoft/TypeScript/blob/main/src/executeCommandLine/executeCommandLine.ts

https://github.com/microsoft/TypeScript/blob/main/src/compiler/commandLineParser.ts#L586

System233 commented 1 year ago

Okay, PR #56051 is suspended, now let's continue from here.

There are a few questions for all

Comments

I don't think this should happen, I think it's pretty valuable to have a reference when you use tsc --init

Originally posted by @orta in https://github.com/microsoft/TypeScript/issues/56051#issuecomment-1759290942

Yes, it's very valuable, but only for the first time, and why don't you use it in your repository tsconfig/bases like this? Source: tsconfig/bases/node20.json

--- "tsconfig/bases/node20.json"
+++ "tsconfig/bases/node20-valuable-version.json"  
@@ -1,17 +1,113 @@
 {
-  "$schema": "https://json.schemastore.org/tsconfig",
-  "display": "Node 20",
-  "_version": "20.1.0",
-
+  "$schema": "https://json.schemastore.org/tsconfig", /* JSON schema used for validation and intellisense in editors.*/
+  "display": "Node 20",                               /* Non-standard field: This field doesn't have official documentation or may be used for internal purposes.*/
+  "_version": "20.1.0",                               /* Non-standard field: This field doesn't have official documentation or may be used for internal purposes.*/
+
   "compilerOptions": {
-    "lib": ["es2023"],
-    "module": "node16",
-    "target": "es2022",
-
-    "strict": true,
-    "esModuleInterop": true,
-    "skipLibCheck": true,
-    "forceConsistentCasingInFileNames": true,
-    "moduleResolution": "node16"
+    /* Visit https://aka.ms/tsconfig to read more about this file */
+
+    /* Projects */
+    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
+    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
+    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
+    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
+    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
+
+    /* Language and Environment */
+    "target": "es2023",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+    "lib": ["es2023"],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
+    // "experimentalDecorators": true,                   /* Enable experimental support for legacy experimental decorators. */
+    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
+    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
+    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
+    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
+
+    /* Modules */
+    "module": "node16",                                /* Specify what module code is generated. */
+    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
+    "moduleResolutions": "node16",                     /* Specify how TypeScript looks up a file from a given module specifier. */
+    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
+    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
+    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
+    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
+    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
+    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
+    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
+    // "allowImportingTsExtensions": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
+    // "resolvePackageJsonExports": true,                /* Use the package.json 'exports' field when resolving package imports. */
+    // "resolvePackageJsonImports": true,                /* Use the package.json 'imports' field when resolving imports. */
+    // "customConditions": [],                           /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
+    // "resolveJsonModule": true,                        /* Enable importing .json files. */
+    // "allowArbitraryExtensions": true,                 /* Enable importing files with any extension, provided a declaration file is present. */
+    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
+
+    /* JavaScript Support */
+    // "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
+    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+    /* Emit */
+    // "declarations": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
+    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
+    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
+    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
+    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+    // "outDir": "./",                                   /* Specify an output folder for all emitted files. */
+    // "removeComments": true,                           /* Disable emitting comments. */
+    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
+    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
+    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
+    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
+    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
+    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
+    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
+    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
+    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
+    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+    /* Interop Constraints */
+    // "isolatedModule": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
+    // "verbatimModuleSyntax": true,                     /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
+    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
+    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
+    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. 
+    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
+
+    /* Type Checking */
+    "strict": true,                                      /* Enable all strict type-checking options. */
+    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
+    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods */match the original function. */
+    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
+    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */,
+    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
+    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
+    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
+    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
+    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
+    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
+    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
+    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
+    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
+    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
+    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
+    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
+
+    /* Completeness */
+    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
+    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
   }
 }

The tsconfig.json is not an API reference. Maybe you can try creating a project with tsc --init every day. I believe you will spend a lot of time deleting comments because a large number of comments seriously affect the readability of the actual configuration of the project. The best documentation is code, not comments. If you do need documentation, as mentioned in the comments, please visit https://aka.ms/tsconfig.

Originally posted by @System233 in https://github.com/microsoft/TypeScript/issues/56051#issuecomment-1759475803

Let’s see if there are a lot of comments in various configuration files in popular repositories

microsoft/vscode

tsconfig.json tsconfig.base.json tsconfig.monaco.json tsconfig.tsec.json tsconfig.vscode-dts.json

microsoft/fluentui

tsconfig.json tsconfig.base.all.json tsconfig.base.json tsconfig.base.v0.json tsconfig.base.v8.json

microsoft/playwright

tsconfig.json

DefinitelyTyped

tsconfig.json types/*/tsconfig.json

Nest

tsconfig.json tsconfig.spec.json

Vue

tsconfig.json types/tsconfig.json

angular/angular

tsconfig.json */tsconfig.json

There are too many cases to support this PR, even Microsoft itself doesn't like writing a lot of comments in tsconfig.json 👍 .

Originally posted by @System233 in https://github.com/microsoft/TypeScript/issues/56051#issuecomment-1759564057

Next, let's check if there are a significant number of comments in the template configuration file located in tsconfig/bases.

tsconfig/bases

It can be seen that an excellent tsconfig.json should be clean and tidy, without an abundance of unnecessary comments. However, if comments are considered valuable, they should be added to the tsconfig/bases template configuration. Please consider adding comments there rather than removing them @orta .

Originally posted by @System233 in https://github.com/microsoft/TypeScript/issues/56051#issuecomment-1759612433

Some comments from Typescript members

A PR adding the link to the top is OK, but again, we do not want literally every compiler flag listed in the init tsconfig. For example, some of the flags listed here do nothing, are explicitly discouraged, or have dangerous effects.

Originally posted by @RyanCavanaugh in https://github.com/microsoft/TypeScript/issues/34686#issuecomment-546119586

Reopening in case you want to just make the PR about providing the link to other options. In that case, I would also suggest we remove the emitted comment descriptions because they tend to be a major pain when using tsc --init.

Originally posted by @DanielRosenwasser in https://github.com/microsoft/TypeScript/issues/34686#issuecomment-546137195

Perhaps someone can conduct a data analysis on the proportion of comment lines in all tsconfig.json files in the DefinitelyTyped repository to determine if an abundance of comments in tsconfig.json is a common occurrence.

The reality is that no one ever writes extensive comments in tsconfig.json. @orta, why don't you keep comments in your project tsconfig/bases? @MartinJohns, why do you always want to remove some of the comments generated by tsc --init in your project? Please keep them intact vscode-inline-types/tsconfig.json.

I will never use @tsconfig/*. Why extend an unrelated project just for a few lines of configuration? It's like saying I know the configuration generated by tsc --init is very ugly, so I choose to cp other-project/tsconfig.json . to start a new project. Isn't it better to have tsc --init generate a basic configuration file, and let developers have direct control over all the settings?

Readability test

Did you see a lot of errors in the tsconfig.json diff snippet above?

crazyjat commented 4 weeks ago

Literally no one wants the comments. It is incredibly stupid that this is the default AND there is no way to disable them. What a waste of everyone's time.

Edit: Got thumbed down by someone that loves unnecessary comments. I hate people like you.

System233 commented 3 weeks ago

This is pure arrogance—completely ignoring the community's voice. Those with a vested interest in the tsconfig/bases repository have no right to oppose here. They don’t even like having comments in their own tsconfig and have chosen to remove all of them, yet they oppose others who want to remove comments from their tsconfig. If you don't even use it yourself, why force it on others? Is this the infamous double standard at work? Please, just put the comment back in your tsconfig/bases! At the top of the tsconfig file, there’s already a comment linking to the documentation. Even adding a $schema would be a thousand times better than dumping a load of shit into the tsconfig.

crazyjat commented 3 weeks ago

tsc --init is a waste of time. Why have a feature that is completely useless? Especially if I have to spend twice as much time removing the comments. I'll never use it again. Arrogance doesn't even begin to describe it. It's more like hatred for your users.

dcavalcante commented 5 days ago

So.. hear me out: #60407