美文网首页
Typescript 声明文件 .d.ts

Typescript 声明文件 .d.ts

作者: 李霖弢 | 来源:发表于2022-07-21 16:08 被阅读0次

    声明文件用于定义类型而非具体的值,不会保留在编译结果的 js 中。

    TS编译检查时,变量的声明查找顺序
    1. 当前编译上下文找该变量的定义
    2. 变量所在模块的index.d.ts声明文件中查找(或其package.jsontypes字段指向文件)
      通常由npm包的维护者提供
    3. node_modules/@types/npm包名 查找声明。
      通常由社区提供,以@types/开头的声明文件,如:npm install @types/jquery
    4. 通过配置文件 tsconfig.json 中的 pathsbaseUrl 字段指向的其他目录

    全局变量声明

    在script模式中,通过declare进行全局变量声明,通过script标签引入,全局生效。

    type 和 interface

    两者本来就只是类型的定义,因此可以不搭配declare关键字,直接在声明文件中使用
    为了防止命名冲突,通常放在namespace

    声明全局变量
    declare var jQuery: (selector: string) => any;
    declare let jQuery: (selector: string) => any;
    declare const jQuery: (selector: string) => any;
    
    声明函数

    支持函数重载

    declare function jQuery(selector: string): any;
    declare function jQuery(domReadyCallback: () => any): any;
    
    声明类
    declare class Animal {
        name: string;
        constructor(name: string);
        sayHi(): string;
    }
    
    声明枚举
    declare enum Directions {
        Up,
        Down,
        Left,
        Right
    }
    
    声明命名空间

    命名空间(namespace)是TS自己的模块化方案,随着ES6的module广泛运用,已不推荐使用。不同于ES6的module,一个文件里可以有多个namespace。
    目前通常在声明文件中使用,表示一个对象中具有很多子属性。
    通过命名空间.属性来调用内部属性。

    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;
    }
    

    通过声明合并,还可以为系统变量添加新属性,称为扩展全局变量

    interface String {
        prependHello(): string;
    }
    

    模块声明

    .d.ts文件中,如存在export,则为一个模块声明文件,npm包中即使用该方式。
    在模块声明中,只有export导出 + import导入的声明,才会生效。

    可以对每个变量分别export,也可以用declare分别声明,并统一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;
    }
    
    // src/index.ts
    import { name, Options } from 'foo';
    console.log(name);
    let options: Options = {
        data: {
            name: 'foo'
        }
    };
    
    commonjs 规范的声明

    ts中,对采用commonjs规范的库,可以通过以下方式导入:

    • commonjs语法:
    const foo = require('foo');
    const bar = require('foo').bar;
    
    • ESM语法:
    import * as foo from 'foo';
    import { bar } from 'foo';
    
    • TS新增语法import + requireexport =搭配使用:
    // 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规范的声明

    既可以通过 <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;
    }
    
    在module中扩展全局变量

    注意声明文件仍然需要导出一个空对象,用来告诉编译器这是一个模块的声明文件

    // types/foo/index.d.ts
    
    declare global {
        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();
    

    相关文章

      网友评论

          本文标题:Typescript 声明文件 .d.ts

          本文链接:https://www.haomeiwen.com/subject/jofovrtx.html