當使用第三方庫時,需要引用它的聲明文件掏膏,才能獲知其數(shù)據(jù)類型,以獲得對應的代碼補全敦锌、接口提示等功能馒疹。
聲明文件用于定義類型而非具體的值,不會保留在編譯結果的 js 中乙墙。
TS編譯檢查時颖变,變量的聲明查找順序
- 當前編譯上下文找該變量的定義
- 變量所在模塊的
index.d.ts
聲明文件中查找(或其package.json
中types
字段指向文件)
通常由npm包的維護者提供 -
node_modules/@types/npm包名
查找聲明
通常是作者沒有提供聲明文件,由社區(qū)其他開發(fā)者提供听想,以@types/
開頭的聲明文件悼做,如:npm install @types/jquery
- 通過配置文件
tsconfig.json
中的paths
和baseUrl
字段指向的其他目錄
通常是自己本地寫的聲明文件
生成 .d.ts 文件
在tsc
指令中添加 --declaration(簡寫 -d),或者在 tsconfig.json 中添加 declaration 選項哗魂,就可以同時也生成 .d.ts 聲明文件了。
{
"compilerOptions": {
"module": "commonjs",
"outDir": "lib",
"declaration": true,
}
}
全局變量聲明
在script模式中漓雅,通過declare
進行全局變量聲明录别,通過script標簽引入,全局生效邻吞。
注意全局變量文件中不能有import
组题、export
關鍵字,否則會被視為npm/UMD包文件抱冷。
type 和 interface
兩者本來就只是類型的定義崔列,因此不需搭配declare
關鍵字,直接在聲明文件中使用
為了防止命名沖突旺遮,通常放在namespace
下
聲明全局變量
declare var jQuery: (selector: string) => any;
declare let jQuery: (selector: string) => any;
declare const jQuery: (selector: string) => any;
聲明函數(shù)
支持函數(shù)重載
declare function jQuery(selector: string): any;
declare function jQuery(domReadyCallback: () => any): any;
聲明類
注意 declare 里可以聲明類的構造函數(shù)赵讯,interface 里不可以
declare class Animal {
name: string;
constructor(name: string);
sayHi(): string;
}
聲明枚舉
declare enum Directions {
Up,
Down,
Left,
Right
}
聲明命名空間
命名空間(namespace)是TS自己的模塊化方案,隨著ES6的module廣泛運用耿眉,已不推薦使用边翼。不同于ES6的module,一個文件里可以有多個namespace鸣剪。
目前通常在聲明文件中使用组底,表示一個對象中具有很多子屬性丈积。
通過命名空間.屬性
來調(diào)用內(nèi)部屬性。
declare namespace jQuery {
function ajax(url: string, settings?: any): void;
const version: number;
class Event {
blur(eventType: EventType): void
}
enum EventType {
CustomClick
}
}
命名空間也可以嵌套
// src/jQuery.d.ts
declare namespace jQuery {
function ajax(url: string, settings?: any): void;
namespace fn {
function extend(object: any): void;
}
}
//或
declare namespace jQuery.fn {
function extend(object: any): void;
}
// src/index.ts
jQuery.ajax('/api/get_something');
jQuery.fn.extend({
check: function() {
return this.each(function() {
this.checked = true;
});
}
});
聲明合并
同名變量可以重復聲明债鸡,表示有不同的形狀
declare function jQuery(selector: string): any;
declare namespace jQuery {
function ajax(url: string, settings?: any): void;
}
通過聲明合并江滨,還可以為系統(tǒng)變量添加新屬性,稱為擴展全局變量:
interface String {
prependHello(): string;
}
模塊聲明
npm包(ES6)規(guī)范的聲明
.d.ts
文件中厌均,如存在export
唬滑,則為一個模塊聲明文件,npm包中即使用該方式莫秆。
在模塊聲明中间雀,只有export
導出 + import
導入的聲明,才會生效镊屎。
可以對每個變量分別export惹挟,也可以用declare分別聲明,并統(tǒng)一export(注意缝驳,同全局變量聲明文件连锯,type 和 interface 不需要 declare)
// types/foo/index.d.ts
export const name: string;
export interface Options {
data: any;
}
// types/foo/index.d.ts
declare const name: string;
interface Options {
data: any;
}
export { name, Options };
// src/index.ts
import { name, Options } from 'foo';
console.log(name);
let options: Options = {
data: {
name: 'foo'
}
};
commonjs 規(guī)范的聲明
ts中,對采用commonjs規(guī)范的庫用狱,可以通過以下方式導入:
- commonjs語法:
const foo = require('foo');
const bar = require('foo').bar;
- ESM語法:
import * as foo from 'foo';
import { bar } from 'foo';
- TS新增語法
import + require
和export =
搭配使用:
// types/foo/index.d.ts
export = foo;
declare function foo(): string;
declare namespace foo {
const bar: number;
}
// 整體導入
import foo = require('foo');
import * as foo from 'foo';
import foo from 'foo';//當啟用allowSyntheticDefaultImports時
// 單個導入
import bar = foo.bar;
UMD規(guī)范的聲明
既可以通過 <script> 標簽引入运怖,又可以通過 import 導入的庫,需要通過export as namespace
將聲明好的一個變量聲明為全局變量
// types/foo/index.d.ts
export as namespace foo;
export = foo;
declare function foo(): string;
declare namespace foo {
const bar: number;
}
直接擴展全局變量
有的第三方庫擴展了一個全局變量夏伊,可是此全局變量的類型卻沒有相應的更新過來摇展,就會導致 ts 編譯錯誤,此時就需要擴展全局變量的類型溺忧。
注意聲明文件仍然需要導出一個空對象咏连,用來告訴編譯器這是一個模塊的聲明文件
// types/foo/index.d.ts
declare global {
//通過聲明合并,給 String 添加屬性或方法鲁森。
interface String {
prependHello(): string;
}
}
export {};
// src/index.ts
'bar'.prependHello();
模塊插件
declare module
可用于在一個文件中一次性聲明多個模塊的類型祟滴,或擴展某模塊類型
// types/moment-plugin/index.d.ts
import * as moment from 'moment';
declare module 'moment' {
export function foo(): moment.CalendarKey;
}
// src/index.ts
import * as moment from 'moment';
import 'moment-plugin';
moment.foo();
三斜線指令
類似于聲明文件中的 import,它可以用來導入另一個聲明文件歌溉。
三斜線指令必須放在文件的最頂端垄懂,三斜線指令的前面只允許出現(xiàn)單行或多行注釋。
當且僅當在以下幾個場景下痛垛,我們才需要使用三斜線指令替代 import:
- 當我們在書寫一個全局變量的聲明文件時(避免出現(xiàn)
import
草慧、export
關鍵字,以免被識別為npm榜晦、UMD文件)
// types/jquery-plugin/index.d.ts
/// <reference types="jquery" />
declare function foo(options: JQuery.AjaxSettings): string;
// src/index.ts
foo({});
- 當我們需要依賴一個全局變量的聲明文件時
由于全局變量不支持通過 import 導入冠蒋,當然也就必須使用三斜線指令來引入了
// types/node-plugin/index.d.ts
/// <reference types="node" />
export function foo(p: NodeJS.Process): string;
// src/index.ts
import { foo } from 'node-plugin';
foo(global.process);