搞懂TypeScript的类型声明的方方面面

深入解析 TypeScript 中的 .d.ts 语法 TypeScript 的类型系统是其最重要的特性之一。它允许我们在编码过程中显式地定义变量、函数、接口、类等的类型,并进行静态类型检查。通过类型系统,我们可以在编码阶段就发现并修复许多常见的错误,避免在运行时才暴露出问题。类型系统还提供了智能的代码补全、导航和重构功能,帮助我们更快速、更准确地编写代码。接口和类型别名是定义自定义类型的重要工具。接口用于描述对象的形状,而类型别名用于为类型定义一个别名。x: number;y: number; 阅读详情

.d.ts 类型声明/定义文件是 TypeScript 重要的一部分, 希望本文可以带你搞懂下面几个问题:

  • 类型声明是怎么被TypeScirpt识别到的?
  • 怎么使用第三方包的类型声明文件?
  • TypeScript代码怎么编译生成类型声明文件?
  • 怎么为第三方包编写类型声明文件,第三方包类型错误怎么进行修正

类型声明文件

TypeScript 中有两种主要的文件类型 .ts 和 .d.ts,以 .d.ts 为后缀的文件,我们称为 TypeScript 的类型声明文件,主要是用来描述模块内所有导出接口的类型信息(声明文件只是对类型进行定义用来做类型检查,不是代码实现,不能进行赋值)。

类型声明是怎么被引用到的

1.TypeScript 内置类型声明

当你安装 TypeScript 时,会自带很多类型声明:lib。其中 es5.full.d.ts 声明文件包含 JavaScript 运行时以及 DOM 中存在各种常见的环境声明。

img

以 DOM 类型为例:

const aEle = document.querySelector('a') // HTMLAnchorElement | null
const canvasEle = document.querySelector('#my_canvas') as HTMLCanvasElement

我们查找a标签,TypeScript 可以自动推断出类型为 HTMLAnchorElement | null。

如果通过元素ID查找,TypeScript无法推断出具体的元素类型,我们可以使用类型断言来明确指定元素类型为 HTMLCanvasElement(关于断言内容可以阅读:搞懂TypeScript中的类型断言和使用场景)。当变量有明确的类型之后,我们也可以等到更好的类型校验和语法提示。

上面说到的 HTMLAnchorElement 和 HTMLCanvasElement 就是 TypeScript 内置的 DOM 类型声明,也就是 <reference lib="dom" /> 的引用内容,具体内容可以参考:dom.generated.d.ts。

2.第三方包自带的类型声明

一些第三方包会自带类型声明文件,通过 package.json 文件中的 "types" 或 "typings" 字段来指定声明文件位置,以 vue 为例:

{
  "name": "vue",
  "typings": "types/index.d.ts",
  "exports": {
    ".": {
      "import": {
        "node": "./dist/vue.runtime.mjs",
        "default": "./dist/vue.runtime.esm.js"
      },
      "require": "./dist/vue.runtime.common.js",
      "types": "./types/index.d.ts"
    },
    "./dist/*": "./dist/*",
    "./types/*": "./types/*",
    "./package.json": "./package.json"
  },
  "scripts": {
    "build:types": "rimraf temp && tsc --declaration --emitDeclarationOnly --outDir temp && api-extractor run && api-extractor run -c packages/compiler-sfc/api-extractor.json",
    "test:types": "npm run build:types && tsc -p ./types/tsconfig.json",
    "format": "prettier --write --parser typescript "(src|test|packages|types)/**/*.ts"",
    "ts-check": "tsc -p tsconfig.json --noEmit",
    "ts-check:test": "tsc -p test/tsconfig.json --noEmit",
  }
}

vue 是使用 TypeScript 编写的,在 npm scripts build:types 中通过 tsc 命令来生成类型定义文件到临时文件夹 temp:

tsc --declaration --emitDeclarationOnly --outDir temp

并通过 api-extractor 将 temp 中的多个 .d.ts 进行处理和合并。

注意:package.json 使用 types 和 typings 来指定类型声明文件,而非 type,type 用来指定文件模块方案,通常为 module 或 commonjs(默认)。

3.社区维护的声明文件

一些项目中使用的第三方包可能不是使用 TypeScript 编写的,没办法通过代码直接编译生成 .d.ts 声明文件,也没有在包内维护类型声明文件,我们就可以在 TypeScript 社区查找方案。

Definitely Typed是社区维护的声明类库,一些不是使用TypeScript编写的项目,我们可以找到想要的类型声明,极大的简化了JS项目迁移到TS的难度。安装的 @types/xxx 包,都是维护在 Definitely Typed 中。

比如@types/react就可以在 DefinitelyTyped 中找到。

默认情况下项目中安装的@types/react、@types/react-dom 都会被编译器自动引入,TypeScript 会从当前目录向上查找所有 node_modules/@types 中的包,也就是包含 ./node_modules/@types 、../node_modules/@types 等目录。

但是如果在 tsconfig.json 中通过 typeRoots 配置了指定目录,就会自动引入该目录下的类型声明模块。

{
  "compilerOptions": {
    "typeRoots": ["./typings", "node_modules/@types"]
  }
}

注意:typeRoots 默认值为 “node_modules/@types” ,如果指定了其他目录就不会从默认目录中进行查找了,如果还想使用安装的 ”@types/xxx“ ,需要将默认值也添加进来。

怎么确认使用的第三方是否包含类型定义文件?

在 NPM 上会有对应的标签,使用TypeScript编写,会展示有TS标识:
image.png

DefinitelyTyped中维护类型定义,会展示有DT标识:

image.png

TypeScript编写的项目,怎么生成类型定义文件

使用TypeScript 开发的项目中可以通过 tsc 来编译生成类型声明文件,在tsconfig.json中配置一下编译选项:

// tsconfig.json
{
    "compilerOptions": {
        "declaration": true, // 用于指定是否在编译完成后生成相应的*.d.ts文件
        "emitDeclarationOnly": true // 只生成声明文件, 不会生成js文件
    }
}

也可以通过命令行指定参数:

tsc --declaration --emitDeclarationOnly

和上文介绍的 vue 一样,在 package.json 中通过 "types" 或 "typings" 字段来指定类型声明文件即可。

指定编译范围

指定待编译文件有两种方式:

  • 使用 files 属性
  • 使用 include 和 exclude 属性

如果 files 和 include 都未设置,那么除了 exclude 排除的文件,编译器会默认包含路径下的所有 TS 文件。

如果同时设置 files 和 include ,那么编译器会把两者指定的文件都引入。

如果未设置 exclude ,那其默认值为 node_modules 、bower_components、jspm_packages 和编译选项 outDir 指定的路径。

exclude 只对 include 有效,对 files 无效。即 files 指定的文件如果同时被 exclude 排除,那么该文件仍然会被编译器引入。

前面提到,任何被 files 或 include 引入的文件的依赖会被自动引入。

为JS或者第三方代码编写.d.t

在使用TypeScript时,你可能遇到以下问题:

  • 自己使用JS编写的库,不想使用TypeScript重写,为其补充.d.ts
  • 项目中使用的第三方库没有类型声明文件
  • 第三方库缺少某些类型,或者错误定义了某些类型,需要对其进行补充和修正
1. 导入和导出类型定义

如果你想把某个模块相关的类型都定义在一个文件中,可以创建一个.ts 文件,并使用 export 导出,在其他文件中可以直接通过 import 引用。

2. 第三方包类型补充

某些库没有提供类型声明,或者声明类型和实际API不匹配,我们也可以在declare中对其进行补充。

declare可以用来声明全局变量、函数、类或者增强模块的类型:

  • 声明模块:当使用第三方库时,你可以使用 declare 关键字来声明模块的类型,这样可以避免 TypeScript 报错,也可以有更好的类型检查和自动补全。
// global.d.ts
declare module 'my-library-a';

上面的代码中我们声明了my-library-a,但是没有任何类型定义,就会的到隐私的any类型。使用第三方包时,TypeScript总提示类型错误或者缺少类型定义,又不想写类型,就可以使用这种方式。

如果我们只使用到了第三方库的某些方法,或者第三方库的一些类型出现错误,可以使用 declare 进行类型补充

// global.d.ts
declare module 'my-library-b' {  
    export function myFunction(): void;  
    export const myVariable: string;  
}
  • 声明全局变量、函数、对象:
// global.d.ts
declare const A: string;  
declare function B(): void;  
declare interface User {  
    name: string;  
    age: number;  
}  
3. 生成.d.ts工具

微软还提供了一个为第三方库编写声明文件工具: dts-gen,使用dts-gen,可以 从任何 JavaScript 对象生成 TypeScript 定义文件 (.d.ts)。

如果你想为自己写的JS代码或者项目中引入的 NPM 模块编写类型声明,可以使用dts-gen,它会进行类型推断自动生成.d.ts文件。

最后,要让编写的类型声明文件(.d.ts)在项目中生效并使用,你需要将其添加到 tsconfig.json 文件的 include 或 files 中。

{  
"compilerOptions": {  
// 其他配置项...  
},  
"include": [  
"src/**/*.ts",  
"typings/*.d.ts" // 假设你的类型声明文件在 typings 文件夹下  
]  
}  

在上述示例中,我们将 typings/*.d.ts 添加到 include 数组中,以确保 TypeScript 编译器会包含 typings 文件夹下的所有 .d.ts 文件。

tsconfig.json配置复用

我们可以使用 extends 来实现配置复用,即一个配置文件可以继承另一个文件的配置属性。

比如,建立一个基础的配置文件 configs/base.json :

{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}

然后,tsconfig.json 就可以引用这个文件的配置了:

{
  "extends": "./configs/base",
  "files": [
    "main.ts",
    "supplemental.ts"
  ]
}

这种继承有两种特点:

  • 继承者中的同名配置会覆盖被继承者
  • 所有相对路径都被解析为其所在文件的路径
参考文档

理解 Typescript 配置文件

Definitely Typed

欢迎关注公众号“混沌前端”

TypeScript(十二)模块 将体量大的程序拆分成多个小的,功能独立的模块是开发中不可或缺的一环,开发复杂程序的核心之一就是让其变得不复杂。模块化开发可以提高代码的可维护性、可重用性、可扩展性和可测试性,从而提高了开发效率和代码质量,TypeScript沿用了JS的模块概念,在之前文章中我介绍过Node环境下的两种类型兼容,顺带提了一下目前常用的模块导入导出方式:Commonjs和ES Module,这两种方式在TS中被称为是外部模块,除此之外TS还包含了内部模块和全局模块,本文将一一介绍参考文章命名空间和模块 - TypeScript 阅读详情

相关推荐

基于fMRI数据计算脑脊液(CSF)与全脑BOLD信号的时间耦合分析

BOLD和CSF信号有多相似CSF信号要延迟多少时间才能最匹配BOLD信号BOLD-CSF的互相关公式lag:时间延迟采样点数BOLD信号CSF信号延迟时间点对应的相关系数。

Rose9614的博客 2981

d.ts

一.简介 经常看到d.ts,因为一个越来越广泛的应用场景是编辑器智能提示(具体见IntelliSense based on TypeScript Declaration Files): JavaScript IntelliSense can be provided for values declared in a .d.ts file (more info), and types such as interfaces and classes declared in TypeScript are ava

顺其自然~专栏 2391

自适应粒子群优化(Adaptive Particle Swarm Optimization,APSO

下面是一个关于自适应粒子群优化(Adaptive Particle Swarm Optimization,APSO)的博客,希望可以帮助您。提示:以下是本篇文章正文内容,下面案例可供参考在上面的代码中,表示粒子的数量,表示解空间的维度,表示迭代次数,表示优化的目标函数。在__init__方法中,我们初始化了粒子群的位置和速度,并将每个粒子的位置作为其最优解,将其适应度值初始化为正无穷。我们还初始化了学习因子和惯性权重的参数。在run方法中,我们迭代了次,计算每个粒子的适应度值和最优解。

weixin_52026057的博客 9915

TS扩展全局变量类型推导

TS扩展全局变量类型推导 ​ 写这篇文章是因为我在学习vben项目时,在global文件的定义时出现了种种问题,但是在网上又不能及时找到合适的对策 前提概念 声明合并(Declartion Merging) 全局变量如何定义? 操作 然后我们定义一个global.d.ts文件 这是我们定义好了全局的一些变量推导,但是我们ts的检查显示我们出现了一些问题,以下为具体的报错信息 Augmentations for the global scope can only be direct...

Gloomysunny的博客 4564

Elasticsearch 8.17.1 JAVA工具类

整理了Elasticsearch8.17最新版的API工具类

weixin_39555954的博客 1123

global.d.ts 无效问题解决

解决 global.d.ts 不生效问题

知之为知之,不知为不知 3447

ADS2023实战:手把手教你用Load-Pull设计40W LDMOS功率放大器(附工程文件)

本文以飞思卡尔MRF8P9040N LDMOS晶体管为例,详细介绍了在ADS 2023中设计一款40W功率放大器(PA)的全流程。内容涵盖从直流偏置设置、稳定性分析、核心的负载牵引(Load-Pull)仿真,到基于Smith圆图的匹配网络设计、谐波平衡性能验证,直至版图生成与优化。文章提供了手把手的实战指导和工程文件,旨在帮助射频工程师掌握高效率PA的设计方法与关键技巧。

cake8的博客 1070

阮一峰《TypeScript教程》系列之-----一文搞懂d.ts类型声明文件以及项目中如何定义类型文件

单独使用的模块,一般会同时提供一个单独的类型声明文件(declaration file),把本模块的外部接口的所有类型都写在这个文件里面,便于模块使用者了解接口,也便于编译器检查使用者的用法是否正确。类型声明文件里面只有类型代码,没有具体的代码实现。它的文件名一般为的形式,其中d表示declaration(声明)类型声明文件也可以使用export = 命令,输出对外的接口。下面是moment模块的类型声明文件的例子。上面示例中,模块moment内部有一个函数moment(),而export =

Amelian的博客 2954

MTK平台TP驱动设备树与GPIO配置实战解析

本文详细解析了MTK平台TP驱动开发中的设备树与GPIO配置实战。通过DCT工具配置GPIO引脚,结合设备树节点定义触摸参数,并分享驱动移植、编译调试技巧及常见问题解决方案,帮助开发者快速掌握MTK触摸驱动开发核心。

ice55的博客 233

21、博弈中的对抗搜索算法解析

本文深入解析了博弈中的对抗搜索算法,涵盖极小极大算法、阿尔法-贝塔剪枝、移动排序与换位表等核心技术。文章分析了算法的数学基础与实现机制,探讨了其在国际象棋、围棋等复杂游戏中的应用,并扩展至多人游戏中的联盟与合作行为。通过对比不同类型策略的优劣,展示了对抗搜索在实际博弈系统中的演进方向与优化路径,为人工智能决策提供了理论支持与实践指导。

rust6ferris的博客 128

【前端进阶之旅】TypeScript中的类型声明文件

在TypeScript(以下简称TS)的学习和实战中,类型声明文件(.d.ts)是一个贯穿入门到进阶的核心知识点。它不仅能解决“类型缺失”导致的开发提示异常、编译报错,更能让我们在使用第三方JS库时,享受TS带来的类型校验和智能提示,是前端工程化、规范化开发中不可或缺的一环。本文将从“是什么、为什么用、怎么用”三个维度,结合实战场景,带你彻底搞懂TS类型声明文件,帮你在前端进阶之路上再进一步。id:1,name:"张三",addUser(u);id: 1,

程序员林北北的博客 1287

从一只龙虾到一支团队:OpenClaw 单 Bot 多 Agent 配置实践

单 Bot 多 Agent只有一个对外的聊天入口(飞书 Bot)内部有多个独立的 AI Agent,各司其职主 Agent(总指挥)负责接收任务并分配给子 Agent子 Agent 完成任务后将结果返回给主 Agent角色Agent ID职责使用场景🎯 总指挥main-agent统筹协调,任务分发接收所有用户请求✍️ 笔杆子内容创作公众号、博客、小红书🔬 参谋canmou深度研究竞品分析、市场调研📋 运营官operations运营管理邮件、日历、社交媒体。

Maynor的博客 1081

终于搞懂类型声明文件.d.ts和declare了,原来用处如此大

当我们引入第三方库时,ts会自动检索aixos的package.json文件,并通过其types属性查找类型声明文件,查找到index.d.ts这个文件后,就会根据其内部配置进行语法提示。像这种没有内置类型声明文件的,我们就可以自己创建一个xx.d.ts的文件来自己声明,ts会自动读取到这个文件里面的内容的。当我们引入axios时,ts会检索aixos的package.json文件,并通过其types属性查找类型声明文件,查找到index.d.ts这个文件后,就会根据其内部配置进行语法提示。

广漂程序猿DevinRock 3431

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

一文搞懂TypeScript泛型,让你的组件复用性大幅提升

泛型是一个强大的工具,可以帮助我们创建可复用的函数。在TypeScript中,我们可以声明变量和其他数据结构为特定类型,例如对象、布尔值或字符串类型。而通过使用泛型,我们可以处理传递给函数的多种类型的变量。在这篇文章中,我们将学习如何通过泛型实现类型安全,同时不牺牲性能或效率。泛型允许我们在尖括号中定义一个类型参数,如。此外,它们还允许我们编写泛型类、方法和函数。我们将深入探讨在TypeScrip...

前端达人 1230

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

在TypeScript中,如何声明全局模块(Global Modules)以及全局变量?

前端小伙伴们,有没有被TypeScript的"类型报错"搞到想砸键盘过? 引入第三方库时提示"找不到模块",用`window.xxx`时提示"类型不存在",写工具函数想全局使用却要到处`import`...今天咱们就聊聊TypeScript的"全局外挂"——如何声明全局模块和变量,用最接地气的话讲清核心逻辑,看完这篇,你不仅能避开类型报错,还能和面试官唠明白背后的原理~

前端大白话 1514

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

彻底搞懂TypeScript类型定义文件:为什么.d.ts比.ts更重要?

- 引入JavaScript库时TypeScript疯狂报错? - 不知道什么时候该写.d.ts文件什么时候该写.ts文件? - 开源项目中的类型定义文件总是看得一头雾水? 本文将通过解析phuocng/this-vs-that项目的实现方式,帮你彻底搞懂TypeScript类型定义文件的核心原理与应用场景,让你在前端开发中告别类型混乱! 读完本文你将获得: - .d.ts与.ts文件的本质区...

gitblog_00807的博客 1020

别再死记硬背了!用几个真实场景帮你彻底搞懂TypeScript的interface和type

本文通过真实开发场景深入解析TypeScript中`interface`和`type`的核心区别与应用技巧。从API响应类型定义到表单验证系统设计,再到工具函数库和React组件Props,详细展示了如何根据场景选择合适的方式,提升代码可读性和维护性。特别适合正在学习TypeScript的开发者掌握这两种关键类型定义方法。

weixin_30522983的博客 353

Vue3+TS开发实战:解决模块路径与类型声明缺失问题

本文针对Vue3+TypeScript开发中常见的模块路径与类型声明缺失问题,提供了系统解决方案。核心在于通过编写env.d.ts文件声明.vue模块类型,并配置tsconfig.json支持路径别名,从而消除编辑器报错,实现完整的类型安全与智能提示。

assembly8low的博客 925

彻底搞懂CSS Modules在TypeScript中的应用(从入门到生产级配置)

掌握TypeScript与CSS Modules用法,解决样式冲突与类型安全难题。涵盖React/Vue中集成方案、配置步骤及命名约定,提升组件化开发效率与维护性。生产级配置实践,值得收藏。

CodePulse的博客 379

彻底搞懂TypeScript声明合并:接口、命名空间与函数的合并规则

在TypeScript开发中,你是否遇到过同名接口自动合并的情况?是否困惑于命名空间与函数如何共存?声明合并(Declaration Merging)作为TypeScript的核心特性,允许我们将多个同名声明合并为单一实体,这在扩展第三方库类型或组织复杂代码时尤为重要。本文将通过实例解析接口、命名空间与函数的合并规则,帮你掌握这一强大特性。 ## 接口合并:自动聚合成员的魔法 接口合并是最常见...

gitblog_01147的博客 597

一篇文章带你掌握TypeScript全部知识

javascript数据类型为弱数据类型,可以随意改变变量的数据类型,TypeScript数据类型为强数据类型,本文主要讲解TypeScript区别于JavaScript不同的地方。2. TypeScript变量声明。let 变量名:变量类型 = 值。TypeScript类。

qq_41765777的博客 456

Vite 项目中 vite-plugin-eslint 插件 TypeScript 声明文件解析失败:package.json exports 字段的兼容性修复

本文深入解析了Vite项目中vite-plugin-eslint插件因TypeScript 4.7+对package.json exports字段支持变化导致的类型声明文件解析失败问题。通过对比新旧模块解析机制,提供了临时修改node_modules、使用patch-package持久化修复及创建类型声明补丁等多种解决方案,并分享了长期修复建议和通用排查思路,帮助开发者高效解决类似兼容性问题。

weixin_30718391的博客 404

TypeScript学习-第10章:模块与命名空间

上一章咱们搞定了类型断言与缩小,终于能精准拿捏各种类型细节了。可一进入大型项目就傻眼:所有代码堆在一个文件里,像乱炖的大杂烩;变量函数互相污染,改一处牵一发而动全身;第三方库引入后没类型提示,写代码全靠猜……别慌!TypeScript的“代码组织神器”——模块(Module)与命名空间(Namespace)来了!前者负责现代项目的代码拆分与复用,后者兜底旧代码的全局作用域管理,二者联手让你的代码从“一团乱麻”变“井井有条”。今天就用接地气的方式,吃透这两个大型项目必备技能。

Amon的专栏 1066

别再写 AnyScript 了!写给 JS 前端的 TypeScript 入门:彻底搞懂 interface 与 type 的区别

习惯了 JavaScript 的“随心所欲”,却总在复杂业务中被“Cannot read property of undefined”教做人?习惯了用 AI 辅助生成代码,却因为缺少类型约束导致代码逻辑总是跑偏?这篇文章专为具备 JS 基础但对 TS 感到头疼的前端开发者打造。拒绝枯燥的官方文档背诵,我们将从最真实的组件开发和 API 对接场景出发,用大白话带你理清 TypeScript 的底层心智模型,并彻底终结 Interface 与 Type 的架构选型纠结。告别满篇的 AnyScript...

2201_75376519的博客 400

TypeScript 踩坑记录:类属性写不写等号,到底有啥区别?

不写等号,是「先立规矩,东西后面再放」;写等号,是「规矩立好,东西直接放好」。我当初踩这个坑,就是没搞懂「声明类型」和「初始化赋值」根本是两回事,现在搞懂了,再也没因为「属性未定义」报错过。

m0_57836225的博客 343
上一篇: 搞懂TypeScript中的类型断言和使用场景
下一篇: 【文心快码】确实有点东西!
一颗小行星!
博客等级 码龄15年 74粉丝 121原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗小行星!

恰饭ing

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值