# Support for tsconfig.json files #1692

Merged
merged 14 commits into from Jan 21, 2015

## Conversation

Projects
None yet
Member

### ahejlsberg commented Jan 16, 2015

 This PR implements #1667 with some modifications. The presence of a tsconfig.json file in a directory indicates that the directory is the root of a TypeScript project. The tsconfig.json file specifies the root files and the compiler options required to compile the project. A project is compiled in one of the following ways: By invoking tsc with no input files, in which case the compiler searches for the tsconfig.json file starting in the current directory and continuing up the parent directory chain. By invoking tsc with no input files and a -project (or just -p) command line option that specifies the path of a directory containing a tsconfig.json file. When input files are specified on the command line, tsconfig.json files are ignored. An example tsconfig.json file: { "compilerOptions": { "module": "commonjs", "noImplicitAny": true, "removeComments": true, "preserveConstEnums": true, "out": "../../built/local/tsc.js", "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" ] } The "compilerOptions" property can be omitted, in which case the compiler's defaults are used. If no "files" property is present in a tsconfig.json, the compiler defaults to including all files the containing directory and subdirectories. When a "files" property is specified, only those files are included. A tsconfig.json file is permitted to be completely empty, which compiles all files in the containing directory and subdirectories with the default compiler options. Compiler options specified on the command line override those specified in the tsconfig.json file.

### ahejlsberg added some commits Jan 15, 2015

 Support for tsconfig.json files in command-line compiler 
 f9f95ba 
 Hardening compiler to accept empty CompilerOptions object 
 65452aa 
 Adding missing @module to several fourslash tests 
 50b0cb9 
 Default to all files only when none are specified in tsconfig.json 
 960d92f 
 Accepting baselines for corrected error messages 
 ee6f2fa 

### msftclas added the cla-not-required label Jan 16, 2015

 Adding reference to core.ts in sys.ts 
 c342b58 

Merged

Contributor

### Arnavion commented Jan 16, 2015

 This allows watch as a compiler option in the file. Should it be ignored? When input files are specified on the command line, tsconfig.json files are ignored. Why is the entire file ignored instead of just the files section? It would be useful to partially compile a project by specifying individual files, but using the compiler options specified in the project file.
Member Author

### ahejlsberg commented Jan 16, 2015

 @Arnavion I agree, we should probably disallow watch in tsconfig.json. Same for project which only makes sense on the command line. Regarding your second question, I'd like to do what you suggest, but I wonder about this scenario: Say you have directories c:\src\foo and c:\src\bar, each containing a tsconfig.json, and that the current directory is c:\src\foo. Now if you say tsc c:\src\bar\somefile.ts we'd compile a file from the c:\src\bar project with the options of the c:\src\foo project. This may be just fine, but perhaps also confusing.
Member

### DanielRosenwasser commented on 65452aaJan 16, 2015

 This is pretty gross for the negated cases. I'd rather we just use a helper function.
Contributor

### Arnavion commented Jan 16, 2015

 That makes sense. You could expect it to use the tsconfig.json based on the file being compiled (c:\src\bar\tsconfig.json), but then that won't work if you wanted to compile files from both directories with the same commandline. Compiling with the tsconfig.json based on the current directory would be deterministic but, as you said, not intuitive either. One alternative is: For each file, find the tsconfig.json relative to it (the same directory-tree-climbing algorithm as now). If all files map to a single project file, use it. Else print an error ("Multiple project files found. Please specify one with -p") and abort. It'll probably be more common for all the individual files being compiled to be in the same project, so this approach would allow them to be compiled with that project file. On the other hand it's more complicated, and expensive if the files are in multiple directories. Then again, this might not even be really necessary. The use case I was imagining was that someone makes a change to only a few files of a large project and wants to recompile those files, but perhaps they'd be okay with just compiling the whole project every time. Or they could use automation like tsc -watch, watchify, etc. to only compile the changed files. I guess the current behavior is fine.

### NoelAbrahams commented Jan 16, 2015

 @ahejlsberg When a "files" property is specified, only those files are included. I am thinking why would anyone want to have .ts files in a directory and not have them compiled? Perhaps an "exclude": [ "foo/bar.ts" ] would make more sense?
Member

### dbaeumer commented Jan 16, 2015

 +1 for the exclude behavior. One question: can I combine regular command line options with the -p option E.g. tsc -p src -module "commonjs" If you share code between the browser and nodejs and you need to compile the code once for commonjs and once for amd it would make sense to only maintain one tsconfig.json file.

Closed

Member Author

### ahejlsberg commented Jan 16, 2015

 @NoelAbrahams I think there are two important scenarios: (1) Let me drop an empty tsconfig.json file in a directory and have everything in there be a project, and (2) let me describe the exact list of files I want included. The current design covers both with a minimum of complexity. That said, I can certainly see how an "exclude" list could be useful, although I suspect we'd then need globbing as well, so the level of complexity goes up. I definitely don't want this growing into an alternate build system. The intent is more to offer tools (e.g. editors) a simple and deterministic way to decide what the compilation context for a particular file is. @dbaeumer Yes, you can combine other command line options with -p.
 Fixing negated language version checks 
 bce15cb 
Contributor

### mihailik commented on src/compiler/commandLineParser.ts in f9f95baJan 16, 2015

 Looks like when JSON config is used, any *.ts file sitting next to it is automatically included in the build. Why is that? Handling of a config doesn't seem to be much related to a particular behaviour of scanning directories.

### fdecampredon commented Jan 17, 2015

 I think there are two important scenarios: (1) Let me drop an empty tsconfig.json file in a directory and have everything in there be a project, and (2) let me describe the exact list of files I want included. The current design covers both with a minimum of complexity. That said, I can certainly see how an "exclude" list could be useful, although I suspect we'd then need globbing as well, so the level of complexity goes up. I definitely don't want this growing into an alternate build system. The intent is more to offer tools (e.g. editors) a simple and deterministic way to decide what the compilation context for a particular file is. Honestly if your target is editor I would prefer that this feature never make it to master. If those configuration files are implemented, I will have to support them, if I want to offer more complex configuration mechanisms, I will have to support another config file and figure when a file configuration has precedence over another. Build/project configuration has always be a topic where everyone make its own sauce, the amazing number of build/lint/configuration tools is a good example of that. I don't clearly see the value of those tsconfig.json file over storing the command line in simple bash script, however I'm pretty much sure they will give me headache when I'll have to decide how I should integrate them.
Contributor

### basarat commented Jan 18, 2015

 I agree with @fdecampredon that this PR might not be a good idea for IDE developers. Nevertheless Perhaps an "exclude": [ "foo/bar.ts" ] would make more sense? No. Better to have !foo/bar.ts included in files than to add another option to the root. If this PR does get merged I would as a second step recommend making files support the entire glob/minmatch/regexp syntax common in JavaScript build tools. Having a custom hacked exclude option would just be painful to allow that next step. You would pretty soon want to do exclude: node_modules/**/*.
Contributor

### Arnavion commented Jan 18, 2015

 @basarat Anders mentioned that already: That said, I can certainly see how an "exclude" list could be useful, although I suspect we'd then need globbing as well, so the level of complexity goes up. The problem with supporting globbing is that it needs to be an own-implementation, since tsc can't rely on node modules. This is why the previous PR for wildcards was abandoned.
Contributor

### basarat commented Jan 18, 2015

 @Arnavion sorry. Thanks!

### NoelAbrahams commented Jan 18, 2015

 What's wrong with exclude: [ node_modules/**/*]? That's what people do already with .gitignore. I'm not suggesting that exclude be another option, rather it should be the only option. There's no real need for files. A directory already adequately describes that. As I see it: Use the file system to describe the project structure Use .gitignore (or equivalent) to share that structure amongst your team Use tsconfig.json to build the project structure
Member Author

### ahejlsberg commented Jan 18, 2015

 @NoelAbrahams There are actually two very real needs for files: It allows you to specify a file ordering, which matters in projects that use -out. It allows you to reference files outside this directory tree. This is particularly important for referencing declarations files. Yes, you can cover those with ///  but a lot of folks don't like putting those in their programs.

### NoelAbrahams commented Jan 18, 2015

 @ahejlsberg, Ah! I failed to spot the potential for including references. The only objection I have is to the following: When a "files" property is specified, only those files are included. In the project structure we have, all files are included in the compilation, including subdirectories. But certainly, I would like to see ordering and referencing to be part of this.
Member

### DanielRosenwasser commented Jan 18, 2015

 @ahejlsberg, this fails hard if you have a loop in your file system and "files" isn't specified. compiler Daniel$ln -s uhoh . compiler Daniel$ node ../../built/local/tsc.js fs.js:689 return binding.stat(pathModule._makeLong(path)); ^ Error: ELOOP, too many symbolic links encountered 'uhoh' at Object.fs.statSync (fs.js:689:18) at visitDirectory (/Users/Daniel/TypeScript/built/local/tsc.js:1334:40) at Object.readDirectory (/Users/Daniel/TypeScript/built/local/tsc.js:1327:17) at getFiles (/Users/Daniel/TypeScript/built/local/tsc.js:20219:39) at Object.parseConfigFile (/Users/Daniel/TypeScript/built/local/tsc.js:20167:24) at Object.executeCommandLine (/Users/Daniel/TypeScript/built/local/tsc.js:20389:40) === Snip ===  This is mostly a problem if we let others consume this functionality.

### basarat referenced this pull request Jan 18, 2015

Closed

#### tsconfig.json support #7

 Watch for changes to tsconfig.json in -watch mode 
 af61e64 

### NoelAbrahams commented Jan 19, 2015

 Just to clarify my point above. We would like to make use of the external file reference and ordering feature introduced by files, but then we're also forced to include the files that need to be compiled, because one cannot have one without the other as it stands. This introduces a maintenance problem: every time a new file is added or an existing file deleted tsconfig.json needs to be modified; and there is danger of files being inadvertently excluded from compilation. If this change is accompanied by associated changes to the tooling (i.e. in Visual Studio for instance the "Add file" feature should automatically update tsconfig.json) then that should be fine.
Contributor

### basarat commented Jan 19, 2015

 @NoelAbrahams perhaps solvable by a third party tool : support a files-expansion:['!somefile','must/include/**/*.ts'] sort of transform inside tsconfig.json which will expand the files member.
Contributor

### mihailik commented on 45e700eJan 21, 2015

 Shouldn't --declaration option also be present in the services one?

Closed

Closed

### lcorneliussen commented Feb 2, 2015

 Any information yet in which release this will be available? (incl. VS-support?)
Member Author

### ahejlsberg commented Feb 2, 2015

 This will be in the 1.5 release. Not sure yet what level of VS support we'll have in that release.

Closed

Closed

Closed

Closed

Closed

### madskristensen commented Mar 25, 2015

 I've added a JSON Schema for this format on http://json.schemastore.org/tsconfig
Contributor

### basarat commented Mar 25, 2015

 @madskristensen cool. But its incomplete. Complete list (I think): https://github.com/TypeStrong/atom-typescript/blob/master/lib/main/tsconfig/tsconfig.ts#L12-L37 I also wrote a simple validator : https://github.com/TypeStrong/atom-typescript/blob/master/lib/main/tsconfig/tsconfig.ts#L40-L68

### madskristensen commented Mar 25, 2015

 @basarat Awesome. Thanks. Are you sure all those options are supported in tsconfig.json files too? Where's the official documentation for these options so I can get the proper description text?
Contributor

### basarat commented Mar 25, 2015

 Are you sure all those options are supported in tsconfig.json files too I assumed so. Considering they added watch to tsconfig.json as well #2222 (which I think might be a bad idea but nonetheless). Pinging @mhegazy for an exact answer. Where's the official documentation for these options so I can get the proper description text Your best bet : for an up to date list: https://github.com/Microsoft/TypeScript/blob/master/src/compiler/commandLineParser.ts#L7-L175

### madskristensen commented Mar 25, 2015

 Thanks for the link to the commandLineParser.ts for the definitions. I've updated the schema to reflect the entire list of options. http://json.schemastore.org/tsconfig

### mhegazy commented Mar 25, 2015

 thanks @madskristensen, experimental switches are not guaranteed to work, and can be removed. so i would not add them to the schema.

### madskristensen commented Mar 25, 2015

 Thanks, I've removed the experimental options

### Acaspita commented Apr 13, 2015

 Is files:['./someDirectory/'] ( == files:['someDirectory/'] )  equivalent to files:['./someDirectory/**/*.ts']  ? If not so, could you add support for this? I wouldn't like compiler to waste time looking into /bower_components/ or /node_modules/ folders, meaning that I'd like to "easily" specify the folders to include in the project... (* Function Definition *) function Salute(): string; var (* mmm... none... *) begin writeln( 'Thank you :)'); end; 
Contributor

### basarat commented Apr 13, 2015

 equivalent to No. It must point to a file. No gobbing support yet. Requested here : #1927

### srackham commented May 5, 2015

 Is there a reason that the --rootDir tsc command option is not included in the tsconfig.json schema? I'm using 1.5.0-beta.

### mhegazy commented May 5, 2015

 @srackham we have not updated the schema yet.. will look into it. thanks for reporting this. filed #3046 to get it fixed.

### OleksandrChekhovskyi commented on 25e52a3May 7, 2015

 Why did this happen? This change prevents sharing code using symlinks (for example, .d.ts files), which I think is a perfectly valid use case.
Member Author

### ahejlsberg replied May 7, 2015

 Symlink references can be circular so we'd need to keep track of how many we have traversed and stop at some limit. It would add some complexity, but it is certainly doable. A PR would be welcome if you're so inclined.

### OleksandrChekhovskyi replied May 7, 2015

 Could you provide a motivational example of the case when this can happen? I don't quite see how recursive symlinks can emerge in a legitimate codebase, except by mistake. It feels like that should just be an error. And it is by default, here is an example trace when trying to stat a circular symlink: fs.js:797 return binding.stat(pathModule._makeLong(path)); ^ Error: ELOOP, too many symbolic links encountered 'a' at Error (native) at Object.fs.statSync (fs.js:797:18) at Object. (~/temp/test.js:3:16) at Module._compile (module.js:460:26) at Object.Module._extensions..js (module.js:478:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:501:10) at startup (node.js:129:16) at node.js:814:3 

### robertbaker commented Jun 9, 2015

 I think it's a bit silly to disallow globs because a small percentage of use-cases would not work, when the majority of use-cases need it.

### httpete commented Jul 15, 2015

 The use for filesGlob is so great - to do exclusions of the node_modules and other dirs, which cause tsc to choike. VSCode is crippled without this.

Closed

### mhegazy commented Jul 24, 2015

 More details can be found at: https://github.com/Microsoft/TypeScript/wiki/tsconfig.json

### matthew-dean commented Jul 30, 2015

 sigh I wish that: a) The web community would unify on adopting a .config directory in the root of a project to store this eve-expanding list of config files. b) Config file definitions could be unified into a standard format. Why can't it just be config.json, with a definition specific for TypeScript, like package.json? And then Sass, Less, and others could all define their respective config.json settings (or alternatively, .config/config.json), that an IDE could import? I think it's really unfortunate this idea was implemented in this way. 😢
Contributor

### nojvek commented Dec 10, 2015

 Isn't that what the.{file} notation is for. Files that are hidden and special.What's wrong with having .gitignore, .vscode, .tsconfig. they all target different purposes.

Merged