Angular2+ typescript 项目里面用require

在typescript里面怎么使用require方法呢?

const jQuery = require('jquery');
const fip = require( '@fonticonpicker/fonticonpicker' )( jQuery );

如果什么都不做,直接在项目里面使用,会得到以下错误:

`Cannot find name 'require' 

以下方法可以解决上面的错误:

1. Install using yarn add @types/node or npm install @types/node --save-dev
2. Add "node" to the "types" option in your tsconfig.json, so it looks like "types": ["node"]. 
This makes them available in any file in your project and you don't have to use reference comments.

那么为什么要做第二步呢?其实做不做第二步是要分情况的。想要解释这个问题我们就需要先了解

@types, typeRoots 和 types 三者是什么意思,它们之间有什么关系。下面是官网的解释

https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#types-typeroots-and-types

If typeRoots is specified, only packages under typeRoots will be included. For example:

{
   "compilerOptions": {
       "typeRoots" : ["./typings"]
   }
}

This config file will include all packages under ./typings, and no packages from ./node_modules/@types.

If types is specified, only packages listed will be included. For instance:

{
   "compilerOptions": {
       "types" : ["node", "lodash", "express"]
   }
}

This tsconfig.json file will only include ./node_modules/@types/node, ./node_modules/@types/lodashand ./node_modules/@types/express. Other packages under node_modules/@types/* will not be included.

A types package is a folder with a file called index.d.ts or a folder with a package.json that has a types field.

Specify "types": [] to disable automatic inclusion of @types packages.

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.

总结一下上面一段话的意思就是:

@types 指的是文件夹 ./node-modules/@types/... 下面含有indes.d.ts或者package.json文件的module;
"types":[] 和 "typeRoots": [] 是 tsconfig.json里面的两个配置属性;当types:[]属性设置了,那么只有types属性里面的模块会被加载编译,typeRoots里面的模块会被忽略;
如果types属性没有被设置,那么会加载typeRoots属性里面设置的模块。而用import关键字导入的模块,编译器还是会在node_modules & node_modules/@types两个文件夹下面寻找;


types和typeRoots这两个属性不会影响被import进项目的模块的加载

上面的总结应该解决了我上面提出的问题:为什么第二步做与不做是分情况的。

如果在tsconfig.json文件里面设置了

 "typeRoots": [
      "node_modules/@types"
  ]
如下代码,那么是不需要设置的。因为编译器会默认加载node-modules/@types下面的modules。而如果我们安装了 @types/node,那么node模块是存在node-modules/@types文件夹下面的,
因此是不需要额外把它的加载列在 "types": ["node"] 属性里面。
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": true,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5","typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ]
  }
}

如果你的项目中的tsconfig.json文件中已经设置了 "types": [....] 属性,那么需要把node模块也加在里面;否则编译器只会编译"types":[...]属性中列出来的模块,而不管typeRoots里面列的模块。

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": true,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "types": ["jquery", "node"],
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ]
  }
}