TypeScript入门之模块与命名空间

433 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

简介

小伙伴们在学习的时候有没有发现我们在不同的ts文件里命名同样的变量或方法是会报错的。这跟js是完全不一样的。这是因为ts他们所处的空间是全局的。

假设我们在在一个 TypeScript 工程下建立一个文件 a.ts,我们写如下代码:

const a = 1

如果在相同的工程下我们再建立一个新的文件b.ts,如何写出如下代码:

const a = 2

上面我们在b.ts中定义a的时候就会报错。所以我们需要引入模块系统来规避这个情况。

模块系统

TypeScriptECMAScript 2015 一样,任何包含顶级 import 或者 export 的文件都被当成一个模块。

相反地,如果一个文件不带有顶级的import或者export声明,那么它的内容被视为全局可见的。

比如我们改造一下上面的代码,我们在a.ts文件中改动代码如下:

export const a = 1

那么上面的问题就消失了,原因就是exporta变量变成了局部的命名空间内,与b.ts文件中的全局变量a不再产生冲突。

模块语法

模块语法这块和ES中的importexport用法是一样的。

我们可以用export关键字导出变量或者类型,比如:

// export.ts
export const a = 1
export type Person = {
    name: String
}

如果你想一次性导出,那么你可以:

const a = 1
type Person = {
    name: String
}
export { a, Person }

甚至你可以重命名:

const a = 1
type Person = {
    name: String
}
export { a as b, Person }

那么我们用关键字import导入模块

// import.ts
import { a, Person } from './export';

同样的我们也可以重命名导入的模块:

import { Person as P } from './export';

如果我们不想一个个导入,想把模块整体导入,可以这样:

import * as P from './export';

我们甚至可以导入后导出模块:

export { Person as P } from './export';

当然,除了上面的方法之外我们还有默认的导入导出:

export default (a = 1)
export default () => 'function'

命名空间

命名空间也是用来解决重名问题。

TypeScript 中命名空间使用 namespace 来定义,语法格式如下:

namespace SomeNameSpace1 {
  export const a1 = 1;
  export const str1 = "randy";
  export const say = () => {
    console.log("SomeNameSpace1");
  };
}

使用方式和对象相似。

SomeNameSpace1.a1
SomeNameSpace1.str1
SomeNameSpace1.say

其实命名本质上就是一个对象,上面的命令空间编译如下:

var SomeNameSpace1;
(function (SomeNameSpace1) {
    SomeNameSpace1.a1 = 1;
    SomeNameSpace1.str1 = "randy";
    SomeNameSpace1.say = () => {
        console.log("SomeNameSpace1");
    };
})(SomeNameSpace1 || (SomeNameSpace1 = {}));

我们发现命名空间和模块系统很像,只是比模块系统颗粒度更小。可以在一个文件里面定义多个命名空间,各个空间可以包含相同的属性和方法。

namespace SomeNameSpace1 {
  export const a1 = 1;
  export const str1 = "randy";
  export const say = () => {
    console.log("SomeNameSpace1");
  };
}

namespace SomeNameSpace2 {
  export const a1 = 1;
  export const str1 = "randy";
  export const say = () => {
    console.log("SomeNameSpace2");
  };
}

命名空间定义好了,外部模块怎么使用呢?其实还得用到前面说的模块系统

// namespace1.ts
// 把整个命名空间export出去
export namespace SomeNameSpace1 {
  export const a1 = 1;
  export const str1 = "randy";
  export const say = () => {
    console.log("SomeNameSpace1");
  };
}

在其他模块文件中使用import导入即可使用。

// namespace2.ts
import { SomeNameSpace1 } from "./namespace1";

console.log(SomeNameSpace1.str1); // randy

因为有模块系统的存在,所以我们平时开发基本上用不到命名空间。但是我们还是需要了解,ts中是有命名空间这个概念的。

系列文章

TypeScript入门之环境搭建

TypeScript入门之数据类型

TypeScript入门之函数

TypeScript入门之接口

TypeScript入门之类

TypeScript入门之类型推断、类型断言、双重断言、非空断言、确定赋值断言、类型守卫、类型别名

TypeScript入门之泛型

TypeScript入门之装饰器

TypeScript入门之模块与命名空间

TypeScript入门之申明文件

TypeScript入门之常用内置工具类型

TypeScript入门之配置文件

后记

感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!