type
status
date
slug
summary
tags
category
icon
password
Edited
Jan 13, 2025 03:03 PM
Created
Jan 10, 2025 03:28 AM
在最近的项目开发中,我遇到了一个挑战:如何在不修改核心库代码的情况下,通过插件扩展核心类的数据和方法,并确保这些扩展在使用时能够获得类型提示。这个问题困扰了我很久,尝试了多种方法,包括泛型和类型合并,但这些方法要么过于复杂,要么无法达到预期效果。最终,我发现了
declare
关键字的妙用,它为类型扩展提供了一个简洁而强大的解决方案。下面来讲讲具体的使用。
概念
declare
是 TypeScript 中的一个关键字,用于声明一个变量、函数、类、接口、枚举等的存在,但不会在编译后的 JavaScript 代码中产生任何实际的运行时代码。它主要用于向 TypeScript 编译器提供类型信息,以便进行类型检查和提供代码提示等功能。类型提示
- 声明变量
使用
declare
可以声明一个全局变量的类型。例如:这告诉 TypeScript 编译器,存在一个名为
globalVar
的全局变量,其类型为 string
。这样,在代码中使用 globalVar
时,就能获得相应的类型提示和检查。- 声明函数
可以使用
declare
声明一个函数的类型,包括参数类型和返回值类型。例如:这表示存在一个名为
myFunction
的函数,它接受一个 number
类型的参数和一个 string
类型的参数,并返回一个 boolean
类型的值。在调用 myFunction
时,TypeScript 会根据这个声明进行类型检查。- 声明类
使用
declare
可以声明一个类的结构,包括其属性和方法的类型。例如:这表示存在一个名为
MyClass
的类,它有一个 number
类型的属性 prop
和一个返回 void
的方法 method
。在创建 MyClass
的实例或调用其方法时,TypeScript 会根据这个声明进行类型检查。- 声明接口
declare
也可以用于声明接口,接口用于定义对象的结构。例如:这表示存在一个名为
MyInterface
的接口,它定义了一个对象的结构,该对象必须有一个 string
类型的 key
属性和一个 number
类型的 value
属性。在使用符合 MyInterface
接口的对象时,TypeScript 会根据接口的定义进行类型检查。- 声明枚举
可以使用
declare
声明一个枚举类型。例如:这表示存在一个名为
MyEnum
的枚举,它有三个成员 Value1
、Value2
和 Value3
。在使用 MyEnum
的成员时,TypeScript 会根据枚举的声明进行类型检查。声明模块
在模块化开发中,
declare
可以用于声明模块的结构。通过使用 declare module
,我们可以为一个模块声明其导出的变量、函数、类等的类型。这对于自定义模块或对第三方模块进行类型声明扩展时非常有用。例如:
这表示存在一个名为
my-custom-module
的模块,它导出了一个函数 myFunction
和一个类 MyClass
。在项目中导入并使用这个模块时,TypeScript 会根据这个声明进行类型检查。声明全局变量或扩展全局对象
在一些情况下,我们需要在全局作用域中声明变量或扩展全局对象(如
window
对象)。declare
可以用于这些场景,通过在全局作用域中使用 declare
,我们可以声明全局变量的类型,或者为全局对象添加新的属性或方法的类型声明。例如,为
window
对象添加一个新的属性:这样,
window.myGlobalVar
就有了明确的类型声明,在使用时能够获得类型提示和检查。类型扩展实践
了解了 declare 的使用之后,回到一开始的问题,插件该如何扩展 core 库里面类的属性和方法。
现在假设 core 库里面有一个
Simulator
接口类型。core
-Simulator
然后在
plugin-dashboard
中,我需要去扩展一些大屏相关的属性,就可以利用到 declare
。plugin-dashboard
-Simulator
这里因为是两个库之间的扩展,所以是通过
declare module
去扩展的。记得将声明的类型进行导出,不然不会生效的。
然后最终再在 example 里面去使用的时候,引入该插件,Typescript 便会自动读取扩展的类型。
通过这种方式,可以非常简易的来扩展核心类的属性和方法。
- 作者:JinSo
- 链接:https://jinso365.top/article/177cee95-0faf-8070-ad37-de8f8f2196bb
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。