理解TS中的declare【譯】

JS遷移到TS:爲第三方NPM模塊(非TS開發),寫一個聲明文件node

做者:克里斯.托馬森
Apr 13, 2017
假如,你有一個由多個NPM包組成的APP,對」常規JS項目「來講,這不是一個問題。TS的最大優點就是靜態類型檢查,爲了更好地利用這個優點,咱們須要在」從第三方NPM包中引入代碼「時,爲這些第三方NPM包增長類型聲明。
TS利用聲明文件,來使編譯器理解模塊中的變量類型和函數簽名。然而,如何爲這些第三方NPM包增長聲明文件的方式已經變了。所以,你從網上找到的那些方法,多是過期的。
TS的2.2版本中,有了一個更加直接的方法來爲這些流行的NPM包增長聲明文件。你所要作的是:
npm install --save-dev @types/module
// for example:
npm install --save lodash
npm install --save-dev @types/lodash
npm包管理器將自動在’node_modules/@types'模塊路徑下,根據這些模塊的子路勁建立一個叫’index.d.ts’的文件。這個文件(即’index.d.ts)內部不包含任何業務代碼。這個文件僅僅是一個用來描述組件接口,好比類定義、類型用的。儘管增長了這個文件,這個模塊在使用時,你仍是得老老實實地import進來。
註釋:其實這些第三方廠商,在瞭解TS的趨勢後,在代碼庫編寫了‘類型聲明文件’, 默認安裝的時候不下載。可是能夠經過@types/module的方式去代碼庫主動下載。es6

那若是是那些沒有聲明文件(即該包的供應商沒有編寫‘類型聲明模塊’)的模塊怎麼辦?typescript

不可避免的,你的項目中總有寫npm包,其供應商本沒有爲該包編寫類型聲明文件。若是要在TS文件中利用靜態類型檢測的好處,你就不得不在項目中本身編寫這個包的聲明文件。
我花了數個小時來解決這個問題。TS文檔也沒有跟咱們說怎麼樣來解決這個問題,網上找到的方法不少都是舊版的解決方法。我今天寫個文檔,是但願有人能經過我寫的東西,在面臨相同問題時,能節約一點時間。
首先打開tsconfig.json這個文件,有一個叫typeRoots的屬性,這個屬性是用來定義」哪裏去檢索聲明文件「。默認的,這個屬性是不設置的;並且,在不設置的時候,這個屬性是直接去搜索node_modules/@types下找聲明文件。由於他只會在node_modules文件夾路徑下找,而這個路徑是用來存放包的,你的業務代碼不會放在裏面。
所以,第一步就是在咱們的項目中,增長一個文件夾用來存儲咱們的聲明文件。在這個項目中,咱們將使用」@types「做爲存放路徑,固然,你想用什麼名字就什麼名字。
tsconfig.json
{
"compilerOptions": {npm

"outDir": "./built",
"allowJs": true,
"noImplicitAny": true,
"strictNullChecks": true,
"target": "es6",
"module": "commonjs"

},
"include": [json

"./src/**/*"

],
"exclude": [vim

"node_modules"

]
}
這個配置中,noImplicitAny被誰知成ture,這意味着你必須明確地增長類型聲明。若是你有一個須要遷移不少包的大型項目,你應該把它關掉。
̶I̶t̶ ̶a̶l̶s̶o̶ ̶a̶d̶d̶s̶ ̶t̶y̶p̶e̶R̶o̶o̶t̶s̶:̶ ̶[̶」̶@̶t̶y̶p̶e̶s̶」̶,̶ ̶」̶.̶/̶@̶t̶y̶p̶e̶s̶」̶]̶ ̶.̶ ̶T̶h̶i̶s̶ ̶t̶e̶l̶l̶s̶ ̶t̶h̶e̶ ̶T̶y̶p̶e̶S̶c̶r̶i̶p̶t̶ ̶c̶o̶m̶p̶i̶l̶e̶r̶ ̶t̶o̶ ̶l̶o̶o̶k̶ ̶f̶o̶r̶ ̶.̶d̶.̶t̶s̶ ̶f̶i̶l̶e̶s̶ ̶i̶n̶ ̶b̶o̶t̶h̶ ̶n̶o̶d̶e̶_̶m̶o̶d̶u̶l̶e̶s̶/̶@̶t̶y̶p̶e̶s̶ ̶a̶s̶ ̶w̶e̶l̶l̶ ̶a̶s̶ ̶o̶u̶r̶ ̶c̶u̶s̶t̶o̶m̶ ̶d̶i̶r̶e̶c̶t̶o̶r̶y̶ ̶.̶/̶@̶t̶y̶p̶e̶s̶.̶ Note that all the original JavaScript source files were moved into srcto facilitate TypeScript compiling.
注意,全部的原生代碼被遷移到src路徑下,便於TS解釋器編譯。
2018-02-01更新:在最新版本的TS中,不須要在tsconfig.json中單獨爲typeRoots設置值。
如今,咱們可以建立咱們自定義的聲明文件。在這個例子中,我將展現如何爲一個叫作dir-obj的NPM包編寫一個聲明文件,這是一個我在項目中實際碰到並解決的例子。
讓咱們先建立一個項目安全

mkdir ~/dev/myproject
cd ~/dev/myproject
mkdir src
mkdir built
vim tsconfig.json函數

{
"compilerOptions": {ui

"outDir": "./built",
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
"sourceMap": false

},
"include": [code

"src/**/*"

]
}
vim src/index.ts
<paste>
import * as dirObj from 'dir-obj';
const project = dirObj.readDirectory(__dirname + '/..', {
fileTransform: (file: dirObj.File) => {

return file.fullpath;

}
});
console.log(JSON.stringify(project, null, 2));
</paste>
這個簡單的文件,將實現」讀取項目結構,並輸出每一個文件的全路徑「
在根目錄下,終端中輸入一下代碼,把TS文件編譯成ES5文件:
tsc -p .
-p指令用來告訴tsc編譯器,在當前路徑尋找tsconfig.json文件
警告!沒法找到模塊聲明文件

src/index.ts(1,25): error TS7016: Could not find a declaration file for module 'dir-obj'. '/Users/chris/dev/personal/typescript-examples/node_modules/dir-obj/index.js' implicitly has an 'any' type.
在當前的設置中,ts編譯器不能靜態檢測咱們的代碼是否類型安全,所以,咱們要增長聲明文件。
mkdir src/@types
mkdir src/@types/dir-obj
vim src/@types/dir-obj/index.d.ts
這裏咱們在src路徑下建立了@types的文件夾,以便文件在編譯時被自動地引入。
咱們將爲dir-obj新增一個聲明文件,你的聲明文件必須建在npm包同名的文件夾中。即,上圖中dir-obj文件爲包的同名文件夾。
建立聲明文件

/// <reference types="node" />

declare module 'dir-obj' {
import { Stats } from "fs";

export interface readOptions {

filter?: RegExp | Filter,
dirTransform?: DirTransform,
fileTransform?: FileTransform

}

export type Filter = (file: File) => boolean;
export type DirTransform = (file: File, value: any) => any;
export type FileTransform = (file: File) => any;

export function readDirectory(dir: string, options?: readOptions): object;

export class File {

key: string;
readonly path: string;
readonly fullpath: string;
readonly ext: string;
readonly name: string;
readonly basename: string;

constructor(dir: string, file: string);

readonly attributes: Stats;
readonly isDirectory: boolean;
readonly isRequirable: boolean;

}}咱們在文件的開頭寫上」declare module ‘dir-obj’「,以明確地陳述這個聲明文件所要聲明的npm包。聲明文件剩下的內容中,是一系列原文件中同名的函數和類。不一樣的是,咱們給這些同名類和函數增長了類型信息。須要指出的是,如何解讀JS原包和如何寫一個類型定義,不在本文檔的範疇。可是,仍是但願對你在正確的道路上有所幫助。再次發送」編譯項目「指令tsc -p .最終,再也沒有報編譯錯誤。

相關文章
相關標籤/搜索