TypeScript - 类型声明教程(declare、.d.ts文件、声明文件编写)
作者:hangge | 2026-08-15 10:56
在 TypeScript 开发中,我们经常需要为 JavaScript 库或全局变量添加类型支持。这时就需要用到类型声明(Declaration)。类型声明文件以 .d.ts 为扩展名(d 是 declare 的缩写),用于声明变量、函数、类、模块等的类型信息。它只包含类型声明,不包含具体实现,编译后也不会生成 JavaScript 代码。本文将详细介绍如何编写和使用类型声明文件。


一、基本介绍
1,什么是声明文件
(1).d.ts 文件 是 TypeScript 的声明文件,用于描述 JavaScript 代码的类型信息。它不包含可执行代码,只包含类型声明。
提示:声明文件类似于 C/C++ 中的头文件(.h),用于描述接口规范,而不包含具体实现。
(2)声明文件的作用:
- 为 JavaScript 库提供类型信息
- 让 TypeScript 能够进行类型检查和代码提示
- 在不修改源码的情况下添加类型支持
// 示例:一个简单的声明文件 // hello.d.ts declare function sayHello(name: string): void; // 声明文件只描述类型,不包含实现 // 编译后不会生成任何 JavaScript 代码
2,三种类型声明位置
TypeScript 中的类型声明有三种来源:
- 内置类型声明:TypeScript 自带的类型声明文件,如 lib.dom.d.ts
- 外部定义类型声明:通过 @types/xxx 安装的第三方类型声明
- 自定义类型声明:开发者自己编写的声明文件,如 global.d.ts
3,内置类型声明
(1)内置类型声明是 TypeScript 自带的,包含了 JavaScript 运行时的标准化 API 类型。常见的内置类型声明文件包括:
- lib.es5.d.ts:ES5 标准库类型,如 Array、Object、Function
- lib.dom.d.ts:DOM API 类型,如 Document、HTMLElement、Event
- lib.es2015.d.ts:ES2015 新增类型,如 Promise、Symbol
(2)可以在 tsconfig.json 中通过 lib 字段配置需要的标准库:
注意:如果显式设置了 lib 字段,TypeScript 不会自动添加默认值,需要列出全部所需的库。
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"] // 手动指定需要的标准库
}
}
4,外部类型声明
(1)外部类型声明用于为第三方库添加类型支持。主要有两种方式:
- 库自带声明:库内部包含 .d.ts 文件,如 axios
- @types 包:通过 DefinitelyTyped 仓库维护的社区类型声明
(2)安装 @types 包样例:
提示:大多数流行的 JavaScript 库都有对应的 @types 包,可以在 npm 仓库搜索 @types/库名 来查找。
// 安装 React 的类型声明 npm install @types/react --save-dev // 安装 lodash 的类型声明 npm install @types/lodash --save-dev
二、declare 声明全局变量、全局函数、全局类
1,什么是 declare
(1)declare 关键字用于告诉 TypeScript 编译器某个值已经存在,不需要实现它。declare 的作用如下:
- 声明全局变量、函数、类
- 声明模块和命名空间
- 扩展第三方库的类型定义
(2)自定义声明文件命名可以随意,但必须是 .d.ts 文件,例如:shims-vue.d.ts、global.d.ts、types.d.ts 等。
2,声明全局变量
(1)在 HTML 文件中定义全局变量:
<!-- public/index.html --> <script> // 定义全局变量 const appName = 'Vue.js 3 + TypeScript' const appVersion = '1.0.0' </script>
(2)在 TypeScript 中直接使用会报错:
// main.ts console.log(appName) // 报错:Cannot find name 'appName' console.log(appVersion) // 报错:Cannot find name 'appVersion'
(3)使用 declare 声明全局变量:
提示:声明全局变量后,在项目的任何地方都可以直接使用,不再报错。
// src/types/global.d.ts // 声明全局变量,告诉编译器该变量已声明 declare const appName: string declare const appVersion: string
3,声明全局函数
(1)在 HTML 文件中定义全局函数:
<!-- public/index.html -->
<script>
// 定义全局函数
function getAppName() {
return appName
}
</script>
(2)声明全局函数:
// src/types/global.d.ts // 声明全局函数 declare function getAppName(): string // 或者使用函数类型声明 declare const getAppName: () => string
(3)使用全局函数:
// main.ts console.log(getAppName()) // ok
4,声明全局类
(1)在 HTML 文件中定义全局类:
<!-- public/index.html -->
<script>
// 定义全局类
function Person(name, age) {
this.name = name
this.age = age
}
</script>
(2)声明全局类:
// src/types/global.d.ts
// 声明全局类
declare class Person {
name: string
age: number
constructor(name: string, age: number)
}
(3)使用全局类:
// main.ts
const p = new Person("hangge", 18)
console.log(p)
三、declare 声明文件与模块
1,声明导入的文件
(1)在前端开发中,经常需要导入图片、样式等文件。TypeScript 默认不知道如何处理这些导入,需要声明:
// src/types/global.d.ts // 声明导入图片文件 declare module '*.jpg' declare module '*.jpeg' declare module '*.png' declare module '*.svg' declare module '*.gif' // 声明导入样式文件 declare module '*.css' declare module '*.scss' declare module '*.less'
(2)使用声明的文件导入:
提示:声明模块后,TypeScript 就知道如何处理这些文件的导入,不会再报错。
// main.ts import logoImg from './img/logo.png' // ok import './styles/main.css' // ok
2,声明第三方模块
(1)当使用没有类型声明的 JavaScript 库时,需要手动声明模块。例如使用 lodash:
// 安装 lodash npm install lodash --save // 导入使用 import lodash from 'lodash' // 报错:Could not find a declaration file for module 'lodash'
(2)有两种解决方案,一种方案是安装类型声明包:
npm install @types/lodash --save-dev
(3)另一种方案是手动编写声明文件,手动声明模块的语法如下。
注意:手动声明模块时,只声明实际使用到的方法即可,不需要声明所有方法。
// src/types/global.d.ts
// 声明 lodash 模块
declare module 'lodash' {
// 导出模块中的函数
export function join(args: any[]): any
export function isEmpty(value: any): boolean
// 可以继续导出 lodash 的其他方法
}
3,扩展模块类型
可以为已有的模块添加新的类型定义。例如扩展 axios:
提示:模块扩展(Module Augmentation)允许在不修改原始库的情况下,为第三方库添加额外的类型定义。
// src/types/axios.d.ts
import 'axios'
declare module 'axios' {
interface AxiosInstance {
// 添加自定义方法
customGet(url: string): Promise<any>
}
}
四、声明命名空间
1,declare namespace 语法
(1)declare namespace 用于声明全局对象,该对象包含多个子属性和方法。
(2)典型应用场景是声明通过 CDN 引入的全局库,如 jQuery:
<!-- public/index.html --> <!-- 引入 jQuery --> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
(3)声明 jQuery 的 $ 全局对象:
提示:在 declare namespace 内部,直接使用 function、const、class 等声明成员,不需要再加 declare 关键字。
// src/types/global.d.ts
// 声明 $ 命名空间
declare namespace $ {
function ajax(settings: any): void
function get(url: string, callback: (res: any) => void): void
function post(url: string, data: any, callback: (res: any) => void): void
}
(4)使用声明的全局对象:
// main.ts
// 全局使用 $ 函数不会提示报错
$.ajax({
url: "https://api.example.com/get",
success: (res: any) => {
console.log(res)
}
})
2,嵌套命名空间
(1)命名空间支持嵌套,用于组织复杂的类型结构:
// src/types/global.d.ts
declare namespace MyApp {
// 嵌套命名空间
namespace Utils {
function formatDate(date: Date): string
function parseJSON(str: string): any
}
namespace Config {
const apiUrl: string
const version: string
}
}
// 使用
// MyApp.Utils.formatDate(new Date())
// console.log(MyApp.Config.apiUrl)
附:声明文件最佳实践
1,文件组织结构
(1)推荐的项目类型文件组织方式:
my-project/ ├── src/ │ ├── index.ts │ └── types/ │ ├── global.d.ts // 全局类型声明 │ ├── vue.d.ts // Vue 相关声明 │ └── modules.d.ts // 模块声明
(2)推荐的 tsconfig.json 配置:
提示:即使不配置 typeRoots,只要 .d.ts 文件位于 include 范围内,TypeScript 都能正确识别。
// tsconfig.json
{
"compilerOptions": {
"typeRoots": [
"./node_modules/@types",
"./src/types"
]
},
"include": ["src"]
}
2,发布 npm 包时的配置
(1)如果要发布一个 TypeScript 库,需要在 tsconfig.json 中启用声明文件生成:
// tsconfig.json
{
"compilerOptions": {
"declaration": true, // 自动生成 .d.ts 文件
"outDir": "dist"
}
}
(2)在 package.json 中指定类型文件位置:
注意:types 字段(或 typings 字段)告诉 TypeScript 使用者该库的类型声明文件位置。
// package.json
{
"name": "my-library",
"main": "dist/index.js",
"types": "dist/index.d.ts" // 指定类型声明文件
}
全部评论(0)