首页 前端知识 TypeScript中的“.d.ts“文件详解

TypeScript中的“.d.ts“文件详解

2024-04-30 12:04:14 前端知识 前端哥 313 803 我要收藏

 面向JavaScript编程的你是否已经听说过TypeScript的".d.ts"文件,或者对它有一些困惑?在这篇文章中,我们将全面深入地探讨".d.ts"文件,并试图回答以下问题

  1. .ts.js.d.ts这三种文件之间的关系是什么?
  2. 我们如何使用.d.ts文件?是否意味着我可以永久删除.ts文件?
  3. 如果可以,.d.ts文件如何知道哪个JS文件映射到自己?

".d.ts"文件是什么?

在TypeScript中,".d.ts"文件被用来提供关于JavaScript API的类型信息。当你使用像jQuery或underscore这样的现有JavaScript库时,你可能会希望从你的TypeScript代码中调用这些库。为了避免重写整个库,你可以编写一个".d.ts"文件,其中只包含类型注解。然后,你可以在TypeScript代码中享受静态类型检查的好处,同时仍然使用纯JavaScript库。

例如,考虑以下目录结构:

src/
  my-module.js
  my-module.d.ts
  index.ts

在这个例子中,my-module.js文件定义了一个常量:

const thing = 42;
module.exports = { thing };

然后,我们有一个与之配套的my-module.d.ts文件,它声明了thing的类型:

export declare const thing: number;

最后,在index.ts文件中,我们导入并使用thing

import { thing } from "./my-module"; // <- 没有扩展名

// `thing`的运行时实现取自".js"文件
console.log(thing); // 42

// `thing`的类型声明取自".d.ts"文件
type TypeOfThing = typeof thing; // number

我们可以看到.d.ts文件如何允许我们在不改变原有JavaScript代码的前提下,使用TypeScript的类型系统。

".d.ts"文件的起源和作用

".d.ts"文件是“声明文件”,在TypeScript编译过程中,有一个选项可以生成它。编译器会剥离所有函数和方法体,只保留导出类型的签名。生成的声明文件可以用来描述当第三方开发者从TypeScript中使用JavaScript库或模块时,导出的虚拟TypeScript类型。

声明文件的概念类似于C/C++中的头文件概念。它们可以为现有的JavaScript库手动编写,例如jQuery和Node.js,也有大量的声明文件集合托管在GitHub的DefinitelyTyped中,供流行的JavaScript库使用​。

声明文件的示例:

declare module arithmetics {
    add(left: number, right: number): number;
    subtract(left: number, right: number): number;
    multiply(left: number, right: number): number;
    divide(left: number, right: number): number;
}

在这个例子中,我们定义了一个名为"arithmetics"的模块,它包含四个函数,每个函数接收两个数字作为参数,并返回一个数字。这个声明文件提供了使用这个模块的所有必要类型信息,但并没有包含任何实现细节。

".d.ts"文件与".ts"和".js"文件的关系

".d.ts"文件与".ts"和".js"文件的关系可以从两个角度来理解:文件关系和使用关系。

文件关系

如前所述,".d.ts"文件是TypeScript编译过程中生成的一个选项,它剥离了所有的函数和方法体,仅保留了导出类型的签名。因此,可以看作是".ts"文件的一个“裁剪”版本,只包含类型信息,不包含实现代码。另一方面,".js"文件是".ts"文件经过编译后生成的JavaScript代码,它包含实现细节,但没有类型信息。".d.ts"文件补充了这一点,为".js"文件提供了丢失的类型信息。

使用关系

在实际使用中,".d.ts"文件主要用于提供在JavaScript环境中使用TypeScript的类型信息,使得开发者可以在TypeScript中使用现有的JavaScript库,同时享受到TypeScript的静态类型检查的优势。".d.ts"文件并不能替代".ts"或".js"文件,它们之间是互补的关系,而不是取代的关系。".ts"文件提供了TypeScript代码的实现,".js"文件提供了JavaScript环境的运行代码,而".d.ts"文件则提供了类型信息。

因此,".d.ts"文件并不能知道哪个JS文件映射到它自己。当你在TypeScript中引用一个文件时,如果文件旁边有一个对应的".d.ts"文件,TypeScript会自动包含它的内容。这是因为TypeScript不允许你在import语句的末尾添加".ts"扩展名。如果你引用的文件有一个同名的".d.ts"文件,TypeScript就会使用它的类型信息。

如何使用".d.ts"文件

在使用".d.ts"文件来映射JavaScript项目时,你需要将".d.ts"文件的名称与".js"文件的名称保持一致。每个".js"文件都需要与具有相同名称的".d.ts"文件保持内联(即在同一目录中)。需要从".d.ts"文件中获取类型的JS/TS代码应该指向".d.ts"文件​。

例如,如果你有一个名为"test.js"的文件和一个名为"test.d.ts"的文件,它们都在"testdir/"文件夹中,那么你可以在react组件中这样导入它们:

import * as Test from "./testdir/test";

此外,".d.ts"文件应该像下面这样作为一个命名空间进行导出:

export as namespace Test;

export interface TestInterface1{}
export class TestClass1{}

对于特定的情况,例如你通过npm共享名为"my-module"的模块,你可以通过以下方式安装它:

npm install my-module

然后,你可以像下面这样使用它:

import * as lol from 'my-module';

const a = lol('abc', 'def');

模块的所有逻辑都在"index.js"文件中:

module.exports = function(firstString, secondString) {

  // your code

  return result
}

为了添加类型,你需要创建一个名为"index.d.ts"的文件:

declare module 'my-module' {
  export default function anyName(arg1: string, arg2: string): MyResponse;
}

interface MyResponse {
  something: number;
  anything: number;
}

我们定义了一个名为"my-module"的模块,它有一个默认的导出函数,这个函数接收两个字符串作为参数,并返回一个"myResponse"接口的实例。另外,我们定义了这个接口,它有两个数字类型的属性。

".d.ts"文件的最佳实践

  1. 与JavaScript文件保持一致:".d.ts"文件应与相应的JavaScript文件具有相同的名称,并与之保持内联。

  2. 为导出的类型提供定义:".d.ts"文件允许你为JavaScript库中的各种导出类型(包括函数、对象、类等)提供明确的类型定义。这对于提高代码的可读性和可维护性是非常有用的。

  3. 尽量使用模块化的方式组织代码:".d.ts"文件支持模块化的代码组织方式。你可以创建多个小的、具有明确职责的".d.ts"文件,而不是一个大的包含所有类型定义的文件。这有助于提高代码的可维护性。

  4. 为第三方库创建类型声明文件:如果你正在使用的第三方JavaScript库没有提供类型声明文件,那么你可以自己创建一个。这样,你就可以在使用这个库的同时,享受到TypeScript的类型检查功能。

  5. 使用DefinitelyTyped:DefinitelyTyped是一个大型的类型声明文件集合,包含了许多流行的JavaScript库的类型声明文件。如果你正在使用的库的类型声明文件已经存在于DefinitelyTyped中,那么你可以直接使用它,而不需要自己从头开始创建。

参考内容:关于TypeScript中的"*.d.ts"文件

转载请注明出处或者链接地址:https://www.qianduange.cn//article/6732.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!