为-Vue3-学点-TypeScript-命名空间namespace

31次阅读

共计 2455 个字符,预计需要花费 7 分钟才能阅读完成。

往期目录

第一课, 体验 typescript

第二课, 基础类型和入门高级类型

第三课, 泛型

第四课, 解读高级类型

什么时候要用命名空间?

如果你发现自己写的功能 (函数 / 类 / 接口等 …) 越来越多, 你想对他们进行 分组管理 就可以用 命名空间 , 下面先用 ”“ 举例:

namespace Tools {
    const TIMEOUT = 100;

    export class Ftp {constructor() {setTimeout(() => {console.log('Ftp');
            }, TIMEOUT)
        }
    }

    export class Http {constructor() {console.log('Http');
        }
    }

    export function parseURL(){console.log('parseURL');
    }
}

仔细看你会发现 namespace 下还有 export, export 在这里用来表示哪些功能是可以外部访问的:

Tools.TIMEOUT // 报错, Tools 上没有这个属性
Tools.parseURL() // 'parseURL'

最后我们看下编译成 js 后的代码:

"use strict";
var Tools;
(function (Tools) {
    const TIMEOUT = 100;
    class Ftp {constructor() {setTimeout(() => {console.log('Ftp');
            }, TIMEOUT);
        }
    }
    Tools.Ftp = Ftp;
    class Http {constructor() {console.log('Http');
        }
    }
    Tools.Http = Http;
    function parseURL() {console.log('parseURL');
    }
    Tools.parseURL = parseURL;
})(Tools || (Tools = {}));

看 js 代码能发现, 在 js 中命名空间其实就是一个全局对象. 如果你开发的程序想要暴露一个全局变量就可以用namespace;

如何用命名空间来管理类型?

命名空间不仅可以用在逻辑代码中, 也可以用在 类型, 用来给类型分组:


namespace Food {
    export type A = Window;
    export interface Fruits{
        taste: string;
        hardness: number;
    }

    export interface Meat{
        taste: string;
        heat: number;
    }
}

let meat: Food.Meat;
let fruits: Food.Fruits;

如何引入写好的命名空间?

有 2 种方式, 一种/// <reference path="xxx.ts" />, 还有就是import:

通过 “/// <reference path=’xxx.ts’/>” 导入

通过 reference 进行导入相当于 xxx.ts 文件内的命名空间和当前文件进行了合并:

xxx.ts
// xxx.ts
namespace Food {
    export interface Fruits{
        taste: string;
        hardness: number;
    }
}
yyy.ts
// yyy.ts
<reference path="xxx.ts" />

let meat: Food.Meat;
let fruits: Food.Fruits;

现在在 yyy.ts 中我们就可以直接使用 xxx.ts 中的 Food 类型了, 而不需要使用import.

通过 import 导入

如果命名空间是用 export 导出的, 那么使用的时候就不可以用 /// <reference/> 了, 要用 import 导入:

xxx.ts
// xxx.ts
// 使用 export 导出
export interface Fruits{
    taste: string;
    hardness: number;
}

export interface Meat{
    taste: string;
    heat: number;
}
yyy.ts
// yyy.ts
import {Food} from './xxx'; // 使用 import 导入
let meat: Food.Meat;
let fruits: Food.Fruits;

如何合并多个命名空间

我们知道 接口 是可以合并的, 命名空间 也是可以的, 下面我们把 Vegetables 类型合并到 Food 类型中:

xxx.ts
// xxx.ts
namespace Food {
    export interface Fruits{
        taste: string;
        hardness: number;
    }
}
yyy.ts
// yyy.ts
<reference path="xxx.ts" />
namespace Food {
    export interface Vegetables{
        title: string;
        heat: number;
    }
}

type Vh = Food.Vegetables['heat'] // number;

export=

如果你的 tsconfig 中设置了 "module": "umd",, 那么export = Food 等价于 export default Food, export= 常见于支持 umd 的插件的声明文件.

命名空间在 lodash 里的应用

其实我们看下那些老牌插件 (jq/lodash) 里使用 namespace 特性的代码, 可以发现主要是在声明文件中(xxx.d.ts), 用来表示暴露出来的全局变量(比如 lodash 的 ”_”).

关于声明文件

上面为了解释 命名空间 提及了 声明文件 (xxx.d.ts), 但由于 声明 (declare) 的内容很多, 所以我会在下一节详细介绍.

总结

其实如果你的项目直接是用 ts 写的可能用不上 namespace, 毕竟export 就可以产生 模块, 模块天然就有隔离分组作用.

能力有限, 如果路过大神看到不对的地方还请多多指点, 我必虚心接受.

最后建议大家多写多练, 祝大家早日上手 ts, 放几个我用 ts 写的项目当做参考, 抛砖引玉, 加油!

手势库, 支持点击 / 拖拽 / 旋转 / 缩放: https://github.com/any86/any-…

为 vue 组件生成 this.$xxx 的命令: https://github.com/any86/vue-…

正文完
 0