Typescript 聲明文件 .d.ts

當(dāng)使用第三方庫(kù)時(shí),需要引用它的聲明文件,才能獲知其數(shù)據(jù)類(lèi)型,以獲得對(duì)應(yīng)的代碼補(bǔ)全、接口提示等功能。
聲明文件用于定義類(lèi)型而非具體的值,不會(huì)保留在編譯結(jié)果的 js 中。

TS編譯檢查時(shí),變量的聲明查找順序
  1. 當(dāng)前編譯上下文找該變量的定義
  2. 變量所在模塊的index.d.ts聲明文件中查找(或其package.jsontypes字段指向文件)
    通常由npm包的維護(hù)者提供
  3. node_modules/@types/npm包名 查找聲明
    通常是作者沒(méi)有提供聲明文件,由社區(qū)其他開(kāi)發(fā)者提供,以@types/開(kāi)頭的聲明文件,如:npm install @types/jquery
  4. 通過(guò)配置文件 tsconfig.json 中的 pathsbaseUrl 字段指向的其他目錄
    通常是自己本地寫(xiě)的聲明文件

生成 .d.ts 文件

tsc指令中添加 --declaration(簡(jiǎn)寫(xiě) -d),或者在 tsconfig.json 中添加 declaration 選項(xiàng),就可以同時(shí)也生成 .d.ts 聲明文件了。

{
    "compilerOptions": {
        "module": "commonjs",
        "outDir": "lib",
        "declaration": true,
    }
}

全局變量聲明

在script模式中,通過(guò)declare進(jìn)行全局變量聲明,通過(guò)script標(biāo)簽引入,全局生效。
注意全局變量文件中不能有importexport關(guān)鍵字,否則會(huì)被視為npm/UMD包文件。

type 和 interface

兩者本來(lái)就只是類(lèi)型的定義,因此不需搭配declare關(guān)鍵字,直接在聲明文件中使用
為了防止命名沖突,通常放在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;
聲明類(lèi)

注意 declare 里可以聲明類(lèi)的構(gòu)造函數(shù),interface 里不可以

declare class Animal {
    name: string;
    constructor(name: string);
    sayHi(): string;
}
聲明枚舉
declare enum Directions {
    Up,
    Down,
    Left,
    Right
}
聲明命名空間

命名空間(namespace)是TS自己的模塊化方案,隨著ES6的module廣泛運(yùn)用,已不推薦使用。不同于ES6的module,一個(gè)文件里可以有多個(gè)namespace。
目前通常在聲明文件中使用,表示一個(gè)對(duì)象中具有很多子屬性。
通過(guò)命名空間.屬性來(lái)調(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;
        });
    }
});
聲明合并

同名變量可以重復(fù)聲明,表示有不同的形狀

declare function jQuery(selector: string): any;
declare namespace jQuery {
    function ajax(url: string, settings?: any): void;
}

通過(guò)聲明合并,還可以為系統(tǒng)變量添加新屬性,稱(chēng)為擴(kuò)展全局變量

interface String {
    prependHello(): string;
}

模塊聲明

npm包(ES6)規(guī)范的聲明

.d.ts文件中,如存在export,則為一個(gè)模塊聲明文件,npm包中即使用該方式。
在模塊聲明中,只有export導(dǎo)出 + import導(dǎo)入的聲明,才會(huì)生效。

可以對(duì)每個(gè)變量分別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中,對(duì)采用commonjs規(guī)范的庫(kù),可以通過(guò)以下方式導(dǎo)入:

  • commonjs語(yǔ)法:
const foo = require('foo');
const bar = require('foo').bar;
  • ESM語(yǔ)法:
import * as foo from 'foo';
import { bar } from 'foo';
  • TS新增語(yǔ)法import + requireexport =搭配使用:
// types/foo/index.d.ts
export = foo;
declare function foo(): string;
declare namespace foo {
    const bar: number;
}


// 整體導(dǎo)入
import foo = require('foo');
import * as foo from 'foo';
import foo from 'foo';//當(dāng)啟用allowSyntheticDefaultImports時(shí)

// 單個(gè)導(dǎo)入
import bar = foo.bar;
UMD規(guī)范的聲明

既可以通過(guò) <script> 標(biāo)簽引入,又可以通過(guò) import 導(dǎo)入的庫(kù),需要通過(guò)export as namespace將聲明好的一個(gè)變量聲明為全局變量

// types/foo/index.d.ts

export as namespace foo;
export = foo;

declare function foo(): string;
declare namespace foo {
    const bar: number;
}
直接擴(kuò)展全局變量

有的第三方庫(kù)擴(kuò)展了一個(gè)全局變量,可是此全局變量的類(lèi)型卻沒(méi)有相應(yīng)的更新過(guò)來(lái),就會(huì)導(dǎo)致 ts 編譯錯(cuò)誤,此時(shí)就需要擴(kuò)展全局變量的類(lèi)型。
注意聲明文件仍然需要導(dǎo)出一個(gè)空對(duì)象,用來(lái)告訴編譯器這是一個(gè)模塊的聲明文件

// types/foo/index.d.ts

declare global {
    //通過(guò)聲明合并,給 String 添加屬性或方法。
    interface String {
        prependHello(): string;
    }
}

export {};

// src/index.ts

'bar'.prependHello();
模塊插件

declare module可用于在一個(gè)文件中一次性聲明多個(gè)模塊的類(lèi)型,或擴(kuò)展某模塊類(lèi)型

// 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();
三斜線指令

類(lèi)似于聲明文件中的 import,它可以用來(lái)導(dǎo)入另一個(gè)聲明文件。
三斜線指令必須放在文件的最頂端,三斜線指令的前面只允許出現(xiàn)單行或多行注釋。
當(dāng)且僅當(dāng)在以下幾個(gè)場(chǎng)景下,我們才需要使用三斜線指令替代 import:

  • 當(dāng)我們?cè)跁?shū)寫(xiě)一個(gè)全局變量的聲明文件時(shí)(避免出現(xiàn)import、export關(guān)鍵字,以免被識(shí)別為npm、UMD文件)
// types/jquery-plugin/index.d.ts

/// <reference types="jquery" />

declare function foo(options: JQuery.AjaxSettings): string;


// src/index.ts

foo({});
  • 當(dāng)我們需要依賴(lài)一個(gè)全局變量的聲明文件時(shí)
    由于全局變量不支持通過(guò) import 導(dǎo)入,當(dāng)然也就必須使用三斜線指令來(lái)引入了
// 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);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 看到別人寫(xiě)ts文件的時(shí)候,通常會(huì)有以.d.ts結(jié)尾的文件跟著,它的作用是,描述Javascript模板內(nèi)導(dǎo)出的接口...
    Adder閱讀 8,671評(píng)論 0 6
  • 聲明文件中,declare 表示聲明的意思js原有類(lèi)型必須加declare,js不存在的類(lèi)型不用加,如:inter...
    wyc0859閱讀 7,705評(píng)論 0 1
  • 本文摘自 https://ts.xcatliu.com/basics/declaration-files 聲明文件...
    Lia代碼豬崽閱讀 1,263評(píng)論 0 1
  • 點(diǎn)擊原文 now我們來(lái)看一看TS怎么聲明文件, 在JS里面我們經(jīng)常會(huì)使用各種第三方類(lèi)庫(kù),引入方式也不太相同,常見(jiàn)的...
    videring閱讀 3,238評(píng)論 0 4
  • 當(dāng)使用第三方庫(kù)時(shí),我們需要引用它的聲明文件,才能獲得對(duì)應(yīng)的代碼補(bǔ)全、接口提示等功能。這是因?yàn)榍岸说谌綆?kù)大多都是非...
    CondorHero閱讀 5,139評(píng)論 1 5

友情鏈接更多精彩內(nèi)容