79

I do not understand the meaning of types field in tsconfig.json. In documentation I have read such text:

"types": {
  "description": "Type declaration files to be included in compilation. Requires TypeScript version 2.0 or later.",
  "type": "array",
  "items": {
    "type": "string"
  }
},

As far, as I understand if I install @types/express I should add such string in tsconfig.json

{
  "compilerOptions": {
     ...
     "types": ["lodash"]
   }
} 

but everything works fine without it. And now I do not understand, why I need types field

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Stalso
  • 1,468
  • 2
  • 12
  • 21

3 Answers3

182

As of TypeScript 2.* the 'tsconfig.json' has the following two properties available:

{
    'typeRoots': [],
    'types': [] 
}

I'll detail both in order.


  1. 'typeRoots' specifies root folders in which the transpiler should look for type definitions (eg: 'node_modules').
  • If you've been using typescript, you know that for different libraries that have not been written using typescript, you need definitions in order for the compiler to recognize global variables and to have IntelliSense support.

  • This issue has been tackled by projects (repos) such as 'DefinatelyTyped' that use tools such as tsd or typings module to download typings required for your project, but they also come with their own 'json' file that needs to be maintained separately.

  • With TS2.* you can now fetch definition dependencies using 'npm'. So instead of using a seperate cli library like tsd or typings, you can now just use: npm i @types/{LIB} this way, all dependencies are managed using package.json and you can easily eliminate the necessity of another 'json' file to maintain in your project.


  1. 'types' are the actual library names that will be found in the typeRoot.
  • so let's say you have the default configuration for typeRoots which would look something like:

          "typeRoots": [
              "./node_modules/@types"
          ]
    
  • let's say you now want to use jasmine as a test framework for your project, so you have your typeRoot folder configured, all you have too do now is execute: npm i @types/jasmine --save-dev

  • after the definition package is installed you just need to configure your 'types' property in 'tsconfig.json' as follows:

          "types": [
               "core-js",
               "jasmine",
               "requirejs",
               "chance"
          ]
    

To conclude, basically you tell the TS compiler the following:

typeRoots: You need to look for typings in these folders. types: In one of the folders provided above, you will find definitions for theses framworks (subfolders).

So using the scenario above, and if we add another root:

"typeRoots": [
    "./node_modules/@types",
    "./custom_definitions"
],
"types": [
    "jasmine",
]

TS will now look for definition files in

./node_modules/@types/jasmine

or

./custom_definitions/jasmine

starball
  • 20,030
  • 7
  • 43
  • 238
Vlad Jerca
  • 2,194
  • 1
  • 10
  • 5
  • 2
    Very informative, thanks! Do we still need this at the top of ts files? /// – bedouger Oct 04 '16 at 15:16
  • If you choose to use the type system, no. I personally have no more references in my projects. – Vlad Jerca Oct 04 '16 at 15:27
  • 1
    Do you know why this doesn't work for certain types like moment or sinon but does for others? – Michael Oct 06 '16 at 10:12
  • 1
    @Michael I've tried installing typings for moment just now (**npm i @types/moment**) in order to figure out your problem. If you look closesly the installation ends with an error **`-- UNMET PEER DEPENDENCY watchify@>=3 <4**, so because of this error, the typings don't download. It's not that it doesn't work, it's just that those packages have an unmet peer dependency so they fail to download. – Vlad Jerca Oct 06 '16 at 11:59
  • @Michael Update: Forgot to mention, until the package is fixed, you could manually get the definitions and just create another folder with typings (example up with 'custom_definitions') and just get the definitions from the http://definitelytyped.org/). By doing this, after the '@types' package is fixed you can just update the 'tsconfig.json'. Hope this helps. – Vlad Jerca Oct 06 '16 at 12:11
  • Strange it installed fine for me but the folder just contained a readme saying `@types/moment` is not needed because `moment` already comes with a definitions file which it does when I checked. So I tried `typeRoots:["./node_modules"],types:["moment"]` without success. It does work if I try `import * as moment from 'moment'` in my file but then that turns it into a module which I don't want because my app uses namespaces. Thanks for your help. – Michael Oct 07 '16 at 01:09
  • Solved it, it was a problem with moment.d.ts in that it could only be consumed as an external module. I was able to create a definition file as `import * as moment from 'moment'; export as namespace moment; export = moment;` and now it works fine. – Michael Oct 07 '16 at 03:10
  • @VladJerca I did this, still m getting an error "cannot find name 'require'". Can you please help me with this? – Akanksha Gaur Oct 19 '16 at 07:12
  • @Akanksha please make sure you run *npm uninstall -g typescript* and then reinstall using *npm i -g typescript*. Some conflicts are known to possibly appear. Hope this helps :) – Vlad Jerca Oct 19 '16 at 08:07
  • @VladJerca worked.. mentioned types outside compileroptions by mistake.. thanks – Akanksha Gaur Oct 19 '16 at 08:29
  • 25
    This explanation does not seem correct to me. Looking at the documentation at it states "If types is specified, ONLY packages listed will be included". So usually, you shouldn't specify types otherwise it will limit the type definitions that can be used. – Xcalibur Feb 15 '17 at 01:47
  • 1
    From what I can see, if you don't specify the "types" property, it includes everything it found by default. – Worthy7 Dec 12 '17 at 01:37
  • @Xcalibur Thank you! Your quote from the documentation was key to me solving an issue with an Angular project. Angular specified an empty "types" in tsconfig.app.json ignoring all my \@types. Removing that fixed my build. – a_hardin Jun 25 '19 at 13:35
  • That's extremely straight-forward and useful! Thank you. – Nadav Lebovitch Oct 30 '19 at 06:59
  • @VladJerca Could I get some more clarification on point 2.3. Why is it that this only seems to be required for **some** definition files within @types? I've just came across a scenario where to fix a TypeError (only in vscode) I had to add the typing here ("testing-library__jest-dom"). But usually when I install types they just automatically work. – xaunlopez Jun 30 '20 at 09:49
51

You don't need the types field necessarily. Here is the important part to note from the documentation:

By default all visible “@types” packages are included in your compilation. Packages in node_modules/@types of any enclosing folder are considered visible

So, if you have followed convention or used a tooling set such as npm to download @types packages, you don't need to configure typeRoots or types in your configuration as it will work out of the box with the default folder structure.

User Rebo
  • 3,056
  • 25
  • 30
Xcalibur
  • 3,613
  • 2
  • 32
  • 26
  • 12
    Thank you! Your quote from the documentation was key to me solving an issue with an Angular project. Angular specified an empty "types" in tsconfig.app.json ignoring all my \@types. Removing that fixed my build. – a_hardin Jun 25 '19 at 13:36
6

Small addition to other answers: @types property in tsconfig.json is used mostly for global declarations (logic which you can use without importing modules). So, it won't limit your types if you import. E.g. you have this package: node_modules/@types/foo. And your @types prop equals to [bar]. You will discover that this is still working if foo is a module based logic:

import {A, B, C} from 'foo'

see TS docs:

Keep in mind that automatic inclusion is only important if you’re using files with global declarations (as opposed to files declared as modules). If you use an import "foo" statement, for instance, TypeScript may still look through node_modules & node_modules/@types folders to find the foo package.

Vitaly
  • 930
  • 1
  • 8
  • 10