当前位置: 首页 > news >正文

阮一峰《TypeScript 教程》学习笔记——declare关键字

1. 一段话总结

declare关键字是TypeScript中用于告知编译器“外部已存在特定类型”的纯类型声明工具,仅提供类型描述(不包含具体实现),所有declare语句不进入编译产物,核心用途是解决“引用外部类型(如第三方库、全局对象)时的编译报错”;它支持描述7种类型场景:变量(variable)、函数(function)、类(class)、模块/命名空间(module/namespace)、全局对象扩展(global)、枚举(enum) ,以及用于整合模块类型的类型声明文件(.d.ts),且仅能描述已有类型,无法声明新类型。


2. 思维导图

在这里插入图片描述


3. 详细总结

一、declare 关键字简介

核心维度说明
核心作用告知TypeScript编译器“外部已存在某类型”,避免引用外部类型时的编译报错
本质纯类型声明工具,仅提供类型描述,不包含具体实现
编译特性所有declare语句不进入最终编译产物(仅用于编译时类型检查)
支持场景变量、函数、类、模块、命名空间、全局对象扩展、枚举(共7种核心场景)
限制仅描述已有类型,无法声明新类型(如不能用declare定义新接口)

二、各场景具体用法

1. declare variable(描述外部变量)

  • 作用:定义外部全局变量或第三方库暴露的变量类型。
  • 关键规则
    • 不可设置初始值(仅类型描述,涉及值会报错);
    • 未显式指定类型时,变量默认类型为any
  • 示例代码
    declare let x:number; // 正确:描述外部变量x为number类型
    declare var document; // 正确:document类型为any(未指定类型)
    declare let y:number = 1; // 报错:不可设置初始值
    

2. declare function(描述外部函数)

  • 作用:定义外部函数的参数类型与返回值类型。
  • 关键规则
    • 仅描述函数类型,无函数体实现
    • TypeScript不支持单独的函数类型声明(必须结合declare);
  • 示例代码
    // 正确:描述sayHello函数的类型
    declare function sayHello(name:string):void;
    sayHello('张三'); // 编译通过(外部已实现该函数)// 报错:单独写函数类型声明(无declare)
    function sayHi(name:string):void; 
    

3. declare class(描述外部类)

  • 作用:定义外部类的完整结构(构造器、属性、方法、存取器等)。
  • 支持描述的类成员
    • 静态成员(static)、实例属性(public/private);
    • 构造器(constructor)、实例方法、存取器(get/set);
    • 索引签名(如[index:string]:any);
  • 关键规则:无类的具体实现(如方法体、属性初始值);
  • 示例代码
    declare class Animal {constructor(name:string); // 构造器类型public eat():void; // 实例方法private sleep():void; // 私有实例方法static count:number; // 静态属性get age():number; // 取值器set age(value:number); // 存值器
    }
    

4. declare module / declare namespace(组织外部类型)

  • 作用:将外部模块或命名空间的类型整合,支持扩展外部模块类型。
  • 核心差异与规则
    类型核心用途特殊规则
    declare namespace组织全局类型(如第三方库全局对象)内部可加/不加export,成员默认可访问
    declare module组织模块类型(如ES模块)支持模块名通配符(如my-plugin-*),可扩展已有模块类型(同名接口自动合并)
  • 扩展外部模块类型示例
    // 从moduleA导入Foo接口,扩展其类型
    import { Foo } from './moduleA';
    declare module './moduleA' {interface Foo { // 同名接口自动合并,扩展属性custom: { prop1:string };}
    }
    const a:Foo = { x:0, custom: { prop1:'a' } }; // 编译通过
    

5. declare global(扩展全局对象)

  • 作用:为JavaScript原生全局对象(如Stringwindow)添加新属性/方法的类型。
  • 关键规则
    • 必须在模块文件中使用(需加空导出export {}强制视为模块);
    • 仅能扩充现有全局对象的类型,不能新增顶层全局类型
  • 示例代码
    export {}; // 强制视为模块
    declare global {// 为String原型添加toSmallString方法类型interface String {toSmallString():string;}// 为window添加myAppConfig属性类型interface Window {myAppConfig: { apiUrl:string };}
    }
    // 实现新增方法(类型已通过declare global声明)
    String.prototype.toSmallString = () => 'small';
    const config = window.myAppConfig; // 编译通过
    

6. declare enum(描述外部枚举)

  • 作用:定义外部枚举的类型(如第三方库暴露的枚举)。
  • 支持的枚举形式
    枚举类型语法示例特点
    普通declare enumdeclare enum E1 { A, B }描述外部普通枚举
    显式值declare enumdeclare enum E2 { A=0, B=1 }枚举成员显式赋值
    declare const enumdeclare const enum E3 { A, B }描述外部常量枚举
  • 关键规则:无枚举的具体实现,仅提供成员类型描述。

7. declare 用于类型声明文件(.d.ts)

  • 作用:在单个.d.ts文件中整合多个外部模块的类型(如Node.js的node.d.ts),避免每个文件单独声明。
  • 示例结构node.d.ts部分内容):
    // 声明url模块类型
    declare module "url" {export interface Url { protocol?:string; hostname?:string; }export function parse(urlStr:string):Url;
    }
    // 声明path模块类型
    declare module "path" {export function join(...paths:any[]):string;export var sep:string;
    }
    
  • 引用方式:通过三斜杠命令加载类型声明文件:
    /// <reference path="node.d.ts"/> // 加载类型声明
    import * as url from 'url'; // 编译通过
    

4. 关键问题

问题1:declare关键字的核心特性与普通类型声明(如interface、type)的本质区别是什么?

答案
核心区别体现在“作用对象”“实现要求”“编译产物”三个维度:

  1. 作用对象:declare仅描述外部已存在的类型(如第三方库、全局对象),不创建新类型;普通类型声明(interface/type)用于定义新类型(供当前项目使用);
  2. 实现要求:declare仅提供类型描述,无任何具体实现(如函数无体、类无方法逻辑);普通类型声明需配合具体实现(如class需写方法体);
  3. 编译产物:declare语句不进入最终编译产物(仅用于编译时检查);普通类型声明虽也不生成代码,但依赖其的业务代码会被编译(如用interface约束的变量会保留逻辑)。

问题2:如何使用declare扩展外部模块的类型或JavaScript原生全局对象的类型?请分别举例说明。

答案
需根据“扩展目标”选择不同declare语法:

  1. 扩展外部模块类型:使用declare module "模块名",利用“同名接口自动合并”扩展类型,示例:

    // 1. 导入外部模块的原有类型
    import { Foo } from './moduleA';
    // 2. 用declare module扩展该模块类型
    declare module './moduleA' {interface Foo { // 同名接口自动合并,新增custom属性custom: { prop1:string };}
    }
    // 3. 使用扩展后的类型(编译通过)
    const a:Foo = { x:0, custom: { prop1:'test' } };
    
  2. 扩展全局对象类型:使用declare global(需在模块中,加export {}),示例:

    // 1. 空导出强制视为模块(declare global需在模块中)
    export {};
    // 2. 扩展String原型方法类型
    declare global {interface String {toSmallString():string; // 新增方法类型}
    }
    // 3. 实现新增方法(类型已通过declare声明)
    String.prototype.toSmallString = () => this.toLowerCase();
    // 4. 使用扩展后的方法(编译通过)
    'HELLO'.toSmallString(); // 'hello'
    

问题3:declare enum与普通enum(无declare)的核心差异是什么?在什么场景下需要使用declare enum?

答案
两者核心差异及适用场景如下:

对比维度declare enum普通enum
作用描述外部已存在的枚举(如第三方库暴露的枚举)定义当前项目的新枚举
实现要求仅提供枚举成员类型,无具体实现需定义枚举成员值(默认递增或显式赋值)
编译产物不生成枚举相关代码(仅类型描述)生成JavaScript对象(保留枚举逻辑)

适用场景:仅当需要引用“外部已实现的枚举”(如第三方库通过脚本暴露的全局枚举)时,使用declare enum;例如:

// 第三方库已在全局暴露枚举E(如window.E)
declare enum E { A=0, B=1 }
// 当前项目使用该枚举(编译通过,依赖外部实现)
const val:E = E.A;

若枚举是当前项目定义的,则用普通enum,无需declare。

http://www.dtcms.com/a/527964.html

相关文章:

  • Flutter 异步编程:Future 与 Stream 深度解析
  • 代码训练LeetCode(48)字母异位词分组
  • 每日算法刷题Day79:10.25:leetcode 一般树5道题,用时1h30min
  • 数据分析核心术语略解
  • 南宁网站设计和开发大赛诚信通开了网站谁给做
  • MATLAB基于云模型时间序列预测
  • 【成长纪实】HarmonyOS Next学习地图:新手避坑指南与核心知识点拆解
  • wordpress不适合大型网站网站建设对宣传的意义
  • 大良营销网站建设教程写网站建设需求文档
  • CICD实战(13) - 使用Arbess+GitLab实现.Net core项目自动化部署
  • KingbaseES赋能多院区医院信创转型:浙江省人民医院异构多活数据底座实践解析
  • 微硕WSF2N65 650V N沟MOSFET:汽车PTC辅助加热器“高压启动核”
  • 如何在Mac进行Safari网页长截图?
  • 【2026计算机毕业设计】基于Jsp的汽车租赁信息管理系统
  • LLMs之PE:PromptX(将 AI 智能体从通用助手转变为具备行业/角色能力的交互平台)的简介、安装和使用方法、案例应用之详细攻略
  • AI驱动的DevOps:AI大模型自动化部署、监控和运维流程
  • 汽车销售|汽车推荐|基于SprinBoot+vue的新能源汽车个性化推荐系统(源码+数据库+文档)
  • 佳易王试用版汽车保养维修服务记录查询系统 V17.1:提升汽修门店管理效率的实用工具#汽修保养
  • 我的firefox的新建标签+按钮找不到了
  • 网站建设方案 下载开个网站需要什么
  • 揭阳网站建设维护网站建设 教程
  • HTTP方法的安全性和幂等性
  • HTTP、HTTPS 和 WebSocket 协议和开发
  • 动态规划详细题解——力扣198.打家劫舍
  • 【LeetCode热题100(52/100)】课程表
  • 什么行业必须做网站棋牌软件开发一个多少钱
  • LeetCode:698. 划分为k个相等的子集
  • 【LeetCode100】--- 101.重排链表【思维导图+复习回顾】
  • 【C++:继承】C++面向对象继承全面解析:派生类构造、多继承、菱形虚拟继承与设计模式实践
  • LeetCode 面试经典 150_链表_反转链表 II(60_92_C++_中等)(头插法)