文章目录

  • 模块化和命名空间
  • 🎃模块化
  • 🎃命名空间
  • 类型声明的规则
  • 🎃类型查找
  • 🎃内置类型声明
  • 🎃外部类型声明
  • 🎃自定义类型声明

模块化和命名空间

TypeScript支持两种方式来控制我们的作用域

模块化:每个文件可以是一个独立的模块,支持ES Module(常用),也支持CommonJS;

命名空间:通过namespace来声明一个命名空间

🎃模块化

模块化的使用是和JavaScript一样的

例如我们在其他文件中定义两个工具函数, 可以引入到当前文件中使用

// 其他文件中定义的工具函数
export function sum(num1: number, num2: number) {
  return num1 + num2
}

export function mul(num1: number, num2: number) {
  return num1 * num2
}
// 当前文件夹下引入使用
import {sum, mul} from "./utils/math"

console.log(sum(10, 20))
console.log(mul(10, 20))

🎃命名空间

命名空间在TypeScript早期时,称之为内部模块,主要目的是将一个模块内部再进行作用域的划分,防止一些命名冲突的问题

例如我们有两个函数都命名为format, 一个是用来格式化时间, 一个是用来格式化价格的, 正常情况下, 由于名称相同一定会产生命名冲突问题

// 由于两个函数名相同, 会产生命名冲突
function format(time: string) {
  return "2022-08-15"
}

function format(price: string) {
  return "¥99"
}

这时候我们可以使用命名空间, 对模块内部在进行作用域划分, 防止命名冲突的问题

namespace time {
  // 外部想要访问命名空间的方法, 命名空间中需要导出
  export function format() {
    return "2022-08-15"
  }
}

namespace price {
  export function format() {
    return "¥99"
  }
}

// 使用命名空间方法
time.format()
price.format()

外部文件想要使用我们的命名空间的话, 我们也需要将命名空间导出, 再在要使用的文件中导入即可

// 导出命名空间
export namespace time {
  export function format() {
    return "2022-08-15"
  }
}

类型声明的规则

🎃类型查找

之前我们所有的typescript中的类型,几乎都是我们自己编写的,但是我们也有用到一些其他的类型

const imageEl = document.getElementById("image") as HTMLImageElement

大家是否会奇怪,我们的HTMLImageElement类型来自哪里呢?甚至是document为什么有getElementById的方法呢?

其实这里就涉及到typescript对类型的管理和查找规则了。

我们这里先给大家介绍另外的一种typescript文件: .d.ts文件

我们之前编写的typescript文件都是 .ts 文件,这些文件最终会输出 .js 文件,也是我们通常编写代码的地方;

还有另外一种文件 .d.ts 文件,它是用来做类型的声明(declare)。 它仅仅用来做类型检测,告知typescript我们有哪 些类型;

那么typescript会在哪里查找我们的类型声明呢?或者说这个.d.ts文件来自哪里

内置类型声明;

外部定义类型声明;

自己定义类型声明;


🎃内置类型声明

内置类型声明是typescript自带的、帮助我们内置了JavaScript运行时的一些标准化API的声明文件

比如包括Math、 Date等内置类型,也包括DOM API,比如Window、 Document等;

内置类型声明通常在我们安装typescript的环境中会带有的

GitHub源码链接: https://github.com/microsoft/TypeScript/tree/main/lib

🎃外部类型声明

外部类型声明通常是我们使用一些库(比如第三方库)时,需要的一些类型声明

这些库通常有两种类型声明方式

方式一:在自己库中进行类型声明(编写.d.ts文件),比如axios

方式二:通过社区的一个公有库DefinitelyTyped存放类型声明文件

  • 该库的GitHub地址: https://github.com/DefinitelyTyped/DefinitelyTyped/
  • 我们可以使用网站查询是否有你需要使用库的声明文件: https://www.typescriptlang.org/dt/search?search=
  • 比如我们安装react的类型声明: npm i @types/react --save-dev

🎃自定义类型声明

什么情况下需要自己来定义声明文件呢?

情况一:我们使用的第三方库是一个纯的JavaScript库,没有对应的声明文件;比如lodash

情况二:我们给自己的代码中声明一些类型,方便在其他地方直接进行使用;

例如我们创建一个my.d.ts文件, 可以在该文件中声明自定义的类型

声明变量-函数-类

例如index.html文件中有下面这些代码

<script>
  let myName = "chenyq";
  let maAge = 18;
  
  function myFoo() {
		console.log("foo");
	}

	function myBar() {
		console.log("bar");
	}

	function Person(name, age) {
		this.name = name
		this.age = age
  }
</script>

我是没办法直接在main.js中使用的, 我们可以在自己的my.d.ts文件中进行声明

// 声明变量/函数/类
declare let myName: string
declare let myAge: number

declare function myFoo(): void
declare function myFar(): void

declare class Person {
  name: string
  age: number
  constructor(name: string, age: number)
}

声明模块

declare module 'lodash' {
  export function join(arr: any[]): void
}

声明文件

在某些情况下,我们也可以声明文件

比如在开发vue的过程中,默认是不识别我们的.vue文件的,那么我们就需要对其进行文件的声明;

比如开发中我们使用了 jpg 这类图片文件,默认typescript也是不支持的,也需要对其进行声明;

// 声明文件
declare module '*.vue' {
  import { DefineComponent } from 'vue'
  const component: DefineComponent

  export default component
}

declare module '*.jpg'
declare module '*.jpeg'
declare module '*.png'
declare module '*.svg'
declare module '*.gif'

声明命名空间

我们可以进行命名空间的声明

// 声明命名空间
declare namespace $ {
  export function ajax(settings: any): any
}