TypeScript 全局类型声明:declare关键字的深度解析与实战

TypeScript 全局类型声明:declare关键字的深度解析与实战

引言:declare关键字的本质与哲学

在 TypeScript 中,declare 关键字是类型系统与现实世界的桥梁。它的核心作用是告诉 TypeScript 编译器:"相信我,这个实体在运行时存在,你不需要检查它的实现,但请根据我描述的类型来验证使用它的代码。"

"declare 不是逃避类型检查,而是建立信任边界。" - TypeScript 设计哲学

第一部分:declare 的底层原理与类型系统架构

1.1 TypeScript 编译器如何处理 declare

当 TypeScript 编译器遇到 declare 关键字时,会进入特殊处理模式:

typescript 复制代码
// 源代码分析
declare const VERSION: string;

// 编译器内部处理过程
class DeclareProcessor {
  processDeclareStatement(node: DeclareNode) {
    // 阶段1:语法解析
    const declaration = this.parseDeclaration(node);
    
    // 阶段2:符号表注册
    this.registerSymbol(declaration);
    
    // 阶段3:类型信息附加
    this.attachTypeInfo(declaration);
    
    // 关键:跳过实现检查!
    // 编译器相信声明是真实的,不生成任何运行时代码
  }
  
  registerSymbol(declaration) {
    // 在符号表中标记为"已声明"
    this.symbolTable.set(declaration.name, {
      kind: 'declare',
      type: declaration.type,
      // 特殊标志:只在类型空间存在
      existsIn: ['type-space'],
      // 不会生成到输出中
      emit: false
    });
  }
}

类型系统的双重世界

typescript 复制代码
// 类型空间(Type Space) - 编译时
declare interface User {
  id: string;
  name: string;
}

// 值空间(Value Space) - 运行时
const user: User = {
  id: '123',
  name: 'Alice'
};

// declare 创建的实体只存在于类型空间
// 它们不会出现在 JavaScript 输出中

1.2 declare 与 JavaScript 的运行时类型差异

特性 declare 声明 普通 TypeScript 声明
编译输出 不生成任何代码 生成对应的 JavaScript 代码
类型检查 完全信任声明 检查实现是否符合类型
作用域 可在 .d.ts 文件中使用 可在 .ts 文件中使用
运行时影响 直接影响运行时代码
模块系统 可描述外部模块 描述内部实现

第二部分:declare 的基本用法详解

2.1 声明全局变量

typescript 复制代码
// 声明全局常量
declare const __DEV__: boolean;
declare const __VERSION__: string;
declare const __BUILD_TIME__: number;

// 声明全局变量(可重新赋值)
declare let currentUserId: string | null;

// 声明全局函数
declare function trackEvent(event: string, data?: Record<string, any>): void;

// 声明全局类
declare class ExternalWidget {
  constructor(element: HTMLElement);
  render(data: any): void;
  destroy(): void;
}

// 实际使用
if (__DEV__) {
  console.log(`Version: ${__VERSION__}, Built at: ${new Date(__BUILD_TIME__)}`);
}

currentUserId = 'user-123';
trackEvent('page_view', { path: window.location.pathname });

const widget = new ExternalWidget(document.getElementById('widget'));
widget.render({ title: 'Hello' });

2.2 声明命名空间(全局模块)

typescript 复制代码
// 声明全局命名空间
declare namespace MyApp {
  // 嵌套接口
  export interface Config {
    apiUrl: string;
    timeout: number;
    features: {
      analytics: boolean;
      darkMode: boolean;
    };
  }
  
  // 嵌套函数
  export function initialize(config: Partial<Config>): void;
  
  // 嵌套类
  export class Logger {
    static info(message: string, meta?: any): void;
    static error(error: Error | string): void;
    static warn(message: string): void;
  }
  
  // 嵌套枚举
  export enum LogLevel {
    DEBUG = 0,
    INFO = 1,
    WARN = 2,
    ERROR = 3
  }
  
  // 嵌套常量
  export const DEFAULT_CONFIG: Config;
}

// 使用全局命名空间
MyApp.initialize({
  apiUrl: 'https://api.example.com',
  features: { analytics: true, darkMode: false }
});

MyApp.Logger.info('App initialized');

2.3 声明全局类型别名和接口

typescript 复制代码
// 全局类型别名
declare type UUID = string & { readonly __brand: 'UUID' };
declare type Email = string & { readonly __brand: 'Email' };
declare type RGB = `rgb(${number}, ${number}, ${number})`;
declare type HEX = `#${string}`;

// 全局接口(自动合并到全局作用域)
declare interface GlobalEventMap {
  'user-login': { userId: string; timestamp: number };
  'user-logout': { userId: string };
  'data-loaded': { data: any; source: string };
}

// 全局工具类型
declare type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

declare type Nullable<T> = T | null | undefined;

// 使用全局类型
const userId: UUID = '123e4567-e89b-12d3-a456-426614174000' as UUID;
const userEmail: Email = 'user@example.com' as Email;

function emitEvent<T extends keyof GlobalEventMap>(
  event: T,
  data: GlobalEventMap[T]
): void {
  // 事件派发逻辑
}

第三部分:declare 的高级模式与技巧

3.1 条件声明与环境检测

typescript 复制代码
// 根据环境变量声明不同的全局变量
declare const process: {
  env: {
    NODE_ENV: 'development' | 'production' | 'test';
    [key: string]: string | undefined;
  };
};

// 浏览器环境专属声明
declare namespace browser {
  // 只有浏览器环境才有的API
  export interface Window {
    webkitRequestAnimationFrame?: (callback: FrameRequestCallback) => number;
    mozRequestAnimationFrame?: (callback: FrameRequestCallback) => number;
    msRequestAnimationFrame?: (callback: FrameRequestCallback) => number;
  }
}

// Node.js 环境专属声明
declare namespace node {
  export interface Process {
    pid: number;
    platform: string;
    memoryUsage(): NodeJS.MemoryUsage;
  }
  
  export interface Buffer {
    // Node.js Buffer 特有的方法
    swap16(): Buffer;
    swap32(): Buffer;
    swap64(): Buffer;
  }
}

// 跨平台通用类型
type Platform = 'browser' | 'node' | 'deno' | 'unknown';

declare function getPlatform(): Platform;

// 条件类型声明
declare type PlatformSpecific<T> = 
  Platform extends 'browser' ? T & { browserOnly: true } :
  Platform extends 'node' ? T & { nodeOnly: true } :
  T;

3.2 声明合并与模块增强

typescript 复制代码
// 扩展现有全局接口
interface Window {
  // 添加自定义属性
  myCustomProperty: string;
  
  // 添加自定义方法
  showNotification(message: string, type?: 'info' | 'warning' | 'error'): void;
  
  // 添加可能由浏览器扩展注入的API
  chrome?: {
    runtime: {
      sendMessage(message: any): void;
      onMessage: {
        addListener(callback: (message: any) => void): void;
      };
    };
  };
}

// 扩展 Document 接口
interface Document {
  // 添加实验性API
  exitPointerLock(): void;
  mozExitPointerLock?(): void;
  webkitExitPointerLock?(): void;
  
  // 自定义方法
  getElementById<T extends HTMLElement = HTMLElement>(id: string): T | null;
}

// 扩展 Array 原型(谨慎使用!)
interface Array<T> {
  // 添加自定义方法
  findLast(predicate: (value: T, index: number, obj: T[]) => boolean): T | undefined;
  findLastIndex(predicate: (value: T, index: number, obj: T[]) => boolean): number;
  
  // 添加工具方法
  groupBy<K extends string | number | symbol>(
    keySelector: (item: T, index: number) => K
  ): Record<K, T[]>;
}

// 扩展 String 原型
interface String {
  // 添加格式化方法
  format(...args: any[]): string;
  
  // 添加验证方法
  isEmail(): boolean;
  isPhoneNumber(): boolean;
  
  // 添加转换方法
  toCamelCase(): string;
  toKebabCase(): string;
  toSnakeCase(): string;
}

3.3 高级类型运算与 declare 的组合

typescript 复制代码
// 使用模板字面量类型声明
declare type RouteParam<T extends string> =
  T extends `${string}:${infer Param}/${infer Rest}`
    ? { [K in Param | keyof RouteParam<`/${Rest}`>]: string }
    : T extends `${string}:${infer Param}`
    ? { [K in Param]: string }
    : {};

declare function createRoute<T extends string>(
  path: T
): {
  path: T;
  match(url: string): RouteParam<T> | null;
  build(params: RouteParam<T>): string;
};

// 使用条件类型声明泛型工具
declare type ResolvedPromise<T> = 
  T extends Promise<infer U> ? U : T;

declare type AsyncFunctionReturn<T> =
  T extends (...args: any[]) => Promise<infer R> ? R : never;

// 声明高级映射类型
declare type MappedConfig<T extends Record<string, any>> = {
  [K in keyof T as `config_${string & K}`]: {
    value: T[K];
    description: string;
    editable: boolean;
  };
};

// 使用 infer 进行模式匹配声明
declare type ExtractEventType<T> =
  T extends { type: infer Type } ? Type : never;

declare type ExtractEventData<T, K> =
  T extends { type: K; data: infer Data } ? Data : never;

第四部分:为第三方库创建全局声明

4.1 为无类型库创建全局声明

typescript 复制代码
// 假设有一个名为 legacy-chart 的全局库,通过 <script> 标签引入

// 声明全局变量
declare const LegacyChart: {
  // 构造函数
  new (element: HTMLElement, options?: ChartOptions): ChartInstance;
  
  // 静态方法
  registerTheme(name: string, theme: ThemeOptions): void;
  registerPlugin(name: string, plugin: Plugin): void;
  
  // 静态属性
  version: string;
  defaultTheme: string;
};

// 声明相关类型
declare interface ChartOptions {
  type?: 'line' | 'bar' | 'pie' | 'scatter';
  width?: number;
  height?: number;
  title?: string;
  data?: DataPoint[];
  colors?: string[];
  animation?: boolean;
}

declare interface DataPoint {
  x: number | string;
  y: number;
  label?: string;
}

declare interface ThemeOptions {
  backgroundColor?: string;
  textColor?: string;
  gridColor?: string;
  fontFamily?: string;
}

declare interface Plugin {
  beforeRender?(chart: ChartInstance): void;
  afterRender?(chart: ChartInstance): void;
  beforeUpdate?(chart: ChartInstance, data: DataPoint[]): void;
  afterUpdate?(chart: ChartInstance, data: DataPoint[]): void;
}

declare interface ChartInstance {
  // 实例方法
  render(): void;
  update(data: DataPoint[]): void;
  resize(width: number, height: number): void;
  destroy(): void;
  
  // 实例属性
  readonly element: HTMLElement;
  readonly options: ChartOptions;
  readonly isRendered: boolean;
}

// 使用示例
const chart = new LegacyChart(document.getElementById('chart'), {
  type: 'line',
  width: 800,
  height: 600,
  title: 'Sales Data'
});

chart.render();

4.2 为 jQuery 插件创建声明

typescript 复制代码
// 扩展 jQuery 的接口
interface JQuery {
  // 日期选择器插件
  datepicker(options?: DatepickerOptions): JQuery;
  datepicker(method: 'getDate'): Date | null;
  datepicker(method: 'setDate', date: Date | string): JQuery;
  datepicker(method: 'destroy'): JQuery;
  
  // 工具提示插件
  tooltip(options?: TooltipOptions): JQuery;
  tooltip(method: 'show'): JQuery;
  tooltip(method: 'hide'): JQuery;
  tooltip(method: 'toggle'): JQuery;
  
  // 模态框插件
  modal(options?: ModalOptions): JQuery;
  modal(method: 'show'): JQuery;
  modal(method: 'hide'): JQuery;
  modal(method: 'toggle'): JQuery;
  
  // 通用插件模式
  [pluginName: string]: any; // 为未知插件提供回退
}

// 插件选项接口
interface DatepickerOptions {
  dateFormat?: string;
  minDate?: Date | string;
  maxDate?: Date | string;
  showAnim?: string;
  showButtonPanel?: boolean;
  changeMonth?: boolean;
  changeYear?: boolean;
  yearRange?: string;
}

interface TooltipOptions {
  content?: string | ((response: any) => string);
  position?: {
    my?: string;
    at?: string;
    collision?: string;
  };
  show?: {
    effect?: string;
    delay?: number;
  };
  hide?: {
    effect?: string;
    delay?: number;
  };
  track?: boolean;
}

interface ModalOptions {
  backdrop?: boolean | 'static';
  keyboard?: boolean;
  show?: boolean;
  focus?: boolean;
}

// 使用示例
$('#datepicker').datepicker({
  dateFormat: 'yy-mm-dd',
  minDate: new Date(),
  changeMonth: true,
  changeYear: true
});

$('#tooltip').tooltip({
  content: '这是一个提示信息',
  position: { my: 'left center', at: 'right center' }
});

第五部分:模块系统与 declare 的深度整合

5.1 CommonJS 模块声明

typescript 复制代码
// 声明 CommonJS 模块
declare module 'legacy-commonjs-module' {
  // 导出单个函数
  function mainFunction(param: string): number;
  
  // 导出对象
  const utils: {
    helper1(): void;
    helper2(): void;
  };
  
  // 导出类
  class LegacyClass {
    constructor(value: number);
    doSomething(): void;
  }
  
  // CommonJS 导出语法
  export = {
    mainFunction,
    utils,
    LegacyClass
  };
}

// 使用方式1:require 语法
import legacyModule = require('legacy-commonjs-module');
legacyModule.mainFunction('test');

// 使用方式2:ES6 import(需要开启 allowSyntheticDefaultImports)
import * as legacyModule from 'legacy-commonjs-module';
legacyModule.mainFunction('test');

5.2 UMD 模块声明

typescript 复制代码
// 声明 UMD 模块(同时支持 CommonJS、AMD 和全局变量)
declare module 'umd-library' {
  // 模块导出
  export interface UmdConfig {
    debug: boolean;
    timeout: number;
  }
  
  export function initialize(config: Partial<UmdConfig>): void;
  export class UmdClass {
    constructor();
    method(): void;
  }
  
  // 默认导出(UMD 模块通常有默认导出)
  export default {
    initialize,
    UmdClass
  };
  
  // 全局变量导出(当通过 <script> 标签引入时)
  export as namespace umdLibrary;
}

// 使用方式1:模块导入
import umdLibrary from 'umd-library';
umdLibrary.initialize({ debug: true });

// 使用方式2:全局变量(当通过 <script> 标签引入时)
// umdLibrary 会作为全局变量存在
umdLibrary.initialize({ debug: true });

5.3 ES 模块与 declare 的结合

typescript 复制代码
// 声明 ES 模块
declare module 'modern-es-module' {
  // 命名导出
  export const VERSION: string;
  export const DEFAULT_CONFIG: Config;
  
  export interface Config {
    apiUrl: string;
    retries: number;
    cache: boolean;
  }
  
  export function createClient(config?: Partial<Config>): Client;
  
  export class Client {
    constructor(config: Config);
    fetch<T = any>(endpoint: string): Promise<T>;
    post<T = any>(endpoint: string, data: any): Promise<T>;
  }
  
  // 默认导出
  export default createClient;
  
  // 重新导出
  export { createClient as createApiClient };
}

// 使用示例
import createClient, { VERSION, DEFAULT_CONFIG } from 'modern-es-module';

console.log(`Using version ${VERSION}`);

const client = createClient({
  ...DEFAULT_CONFIG,
  apiUrl: 'https://api.example.com'
});

client.fetch('/users').then(users => {
  console.log(users);
});

第六部分:环境声明与三斜线指令

6.1 环境声明文件 (.d.ts)

typescript 复制代码
// types/global.d.ts - 全局声明文件
declare global {
  // 扩展全局命名空间
  namespace NodeJS {
    interface ProcessEnv {
      NODE_ENV: 'development' | 'production' | 'test';
      API_URL: string;
      SENTRY_DSN?: string;
      ANALYTICS_ID?: string;
    }
  }
  
  // 扩展全局接口
  interface ImportMeta {
    env: {
      MODE: string;
      BASE_URL: string;
      DEV: boolean;
      PROD: boolean;
      SSR: boolean;
    };
  }
  
  // 声明全局变量
  var __DEVTOOLS__: {
    log: (message: string, data?: any) => void;
    time: (label: string) => void;
    timeEnd: (label: string) => void;
  };
}

// 确保这个文件被当作模块
export {};

6.2 三斜线指令详解

typescript 复制代码
// 三斜线指令的四种类型

// 1. 引用类型声明 /// <reference types="..." />
/// <reference types="node" />
/// <reference types="react" />
/// <reference types="webpack/module" />

// 2. 引用路径 /// <reference path="..." />
/// <reference path="./custom-types.d.ts" />
/// <reference path="../shared/types.d.ts" />

// 3. 引用库 /// <reference lib="..." />
/// <reference lib="es2015" />
/// <reference lib="dom" />
/// <reference lib="esnext.asynciterable" />

// 4. AMD 指令 /// <amd-module name="..." /> 和 /// <amd-dependency path="..." />
/// <amd-module name="MyModule" />
/// <amd-dependency path="css!./styles.css" />

// 实际使用示例
// types/global-setup.d.ts
/// <reference types="node" />
/// <reference types="express" />
/// <reference path="./custom.d.ts" />
/// <reference lib="es2015.promise" />

// 现在可以使用 Node.js、Express 和自定义类型了
declare module 'my-module' {
  import { Request } from 'express';
  import { EventEmitter } from 'events';
  
  export interface MyRequest extends Request {
    user?: {
      id: string;
      role: string;
    };
  }
  
  export class MyEmitter extends EventEmitter {
    // ...
  }
}

第七部分:高级技巧与模式

7.1 类型守卫与 declare 的组合

typescript 复制代码
// 声明自定义类型守卫
declare function isString(value: unknown): value is string;
declare function isNumber(value: unknown): value is number;
declare function isArray<T>(value: unknown): value is T[];
declare function isPromise<T>(value: unknown): value is Promise<T>;

// 声明品牌类型(Branded Types)
declare type Brand<T, BrandName extends string> = T & {
  readonly __brand: BrandName;
};

// 具体品牌类型
declare type Email = Brand<string, 'Email'>;
declare type UUID = Brand<string, 'UUID'>;
declare type PositiveNumber = Brand<number, 'PositiveNumber'>;

// 品牌类型验证函数
declare function validateEmail(email: string): email is Email;
declare function validateUUID(uuid: string): uuid is UUID;
declare function validatePositiveNumber(num: number): num is PositiveNumber;

// 使用示例
function processUser(email: string, id: string) {
  if (validateEmail(email) && validateUUID(id)) {
    // 在这里,TypeScript 知道 email 是 Email 类型,id 是 UUID 类型
    sendWelcomeEmail(email); // 类型安全!
    trackUser(id); // 类型安全!
  }
}

function sendWelcomeEmail(email: Email) {
  // 只能接受有效的 Email 类型
}

function trackUser(id: UUID) {
  // 只能接受有效的 UUID 类型
}

7.2 声明高阶类型工具

typescript 复制代码
// 声明深度只读类型
declare type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object
    ? DeepReadonly<T[K]>
    : T[K];
};

// 声明深度可选类型
declare type DeepPartial<T> = {
  [K in keyof T]?: T[K] extends object
    ? DeepPartial<T[K]>
    : T[K];
};

// 声明深度必需类型
declare type DeepRequired<T> = {
  [K in keyof T]-?: T[K] extends object
    ? DeepRequired<T[K]>
    : T[K];
};

// 声明键值对展开类型
declare type Flatten<T> = T extends object
  ? { [K in keyof T]: Flatten<T[K]> }
  : T;

// 声明条件类型工具
declare type If<Condition, Then, Else> = Condition extends true
  ? Then
  : Else;

declare type Equals<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false;

// 声明函数类型工具
declare type Parameters<T> = T extends (...args: infer P) => any ? P : never;
declare type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
declare type ConstructorParameters<T> = T extends new (...args: infer P) => any ? P : never;
declare type InstanceType<T> = T extends new (...args: any[]) => infer R ? R : any;

// 声明异步函数工具
declare type AsyncReturnType<T> = 
  T extends (...args: any[]) => Promise<infer R> ? R :
  T extends (...args: any[]) => infer R ? R : never;

// 声明迭代器工具
declare type ElementType<T> = 
  T extends (infer U)[] ? U :
  T extends readonly (infer U)[] ? U :
  T extends Set<infer U> ? U :
  T extends Map<any, infer V> ? V :
  T extends Promise<infer U> ? U :
  T extends Iterable<infer U> ? U :
  T extends AsyncIterable<infer U> ? U :
  never;

第八部分:实战案例:构建企业级声明系统

8.1 企业级配置系统声明

typescript 复制代码
// types/config.d.ts - 企业配置声明
declare namespace EnterpriseConfig {
  // 基础配置
  export interface BaseConfig {
    appName: string;
    version: string;
    environment: 'development' | 'staging' | 'production';
  }
  
  // 功能标志
  export interface FeatureFlags {
    analytics: boolean;
    sentry: boolean;
    cdn: boolean;
    pwa: boolean;
    ssr: boolean;
  }
  
  // API 配置
  export interface ApiConfig {
    baseUrl: string;
    timeout: number;
    retries: number;
    endpoints: {
      auth: string;
      users: string;
      products: string;
      orders: string;
    };
  }
  
  // 第三方服务配置
  export interface ThirdPartyConfig {
    sentry?: {
      dsn: string;
      environment: string;
    };
    googleAnalytics?: {
      trackingId: string;
      anonymizeIp: boolean;
    };
    stripe?: {
      publishableKey: string;
      apiVersion: string;
    };
  }
  
  // 完整配置
  export type FullConfig = BaseConfig & {
    features: FeatureFlags;
    api: ApiConfig;
    thirdParty: ThirdPartyConfig;
  };
  
  // 配置加载器
  export interface ConfigLoader {
    load(): Promise<FullConfig>;
    get<K extends keyof FullConfig>(key: K): FullConfig[K];
    set<K extends keyof FullConfig>(key: K, value: FullConfig[K]): void;
    watch<K extends keyof FullConfig>(
      key: K,
      callback: (value: FullConfig[K]) => void
    ): () => void;
  }
  
  // 全局配置实例
  export const config: ConfigLoader;
  
  // 环境变量类型
  export type EnvVars = {
    NODE_ENV: string;
    API_URL: string;
    SENTRY_DSN?: string;
    GA_TRACKING_ID?: string;
    [key: string]: string | undefined;
  };
}

// 使用示例
const apiUrl = EnterpriseConfig.config.get('api').baseUrl;
const features = EnterpriseConfig.config.get('features');

if (features.analytics) {
  // 初始化分析
}

8.2 微前端架构中的类型声明

typescript 复制代码
// types/microfrontend.d.ts - 微前端类型声明
declare namespace MicroFrontend {
  // 微应用定义
  export interface MicroApp {
    name: string;
    version: string;
    entry: string;
    activeRule: string | ((location: Location) => boolean);
    props?: Record<string, any>;
    container?: string | HTMLElement;
  }
  
  // 生命周期
  export interface Lifecycle {
    bootstrap: () => Promise<void>;
    mount: (props: any) => Promise<void>;
    unmount: () => Promise<void>;
    update?: (props: any) => Promise<void>;
  }
  
  // 共享依赖
  export interface SharedDependencies {
    react: {
      version: string;
      get: () => Promise<any>;
      loaded?: boolean;
    };
    'react-dom': {
      version: string;
      get: () => Promise<any>;
      loaded?: boolean;
    };
    vue?: {
      version: string;
      get: () => Promise<any>;
      loaded?: boolean;
    };
  }
  
  // 通信机制
  export interface EventBus {
    on: (event: string, handler: Function) => void;
    off: (event: string, handler?: Function) => void;
    emit: (event: string, ...args: any[]) => void;
    once: (event: string, handler: Function) => void;
  }
  
  // 状态共享
  export interface GlobalState {
    get: <T = any>(key: string) => T | undefined;
    set: <T = any>(key: string, value: T) => void;
    subscribe: (key: string, callback: (value: any) => void) => () => void;
  }
  
  // 微前端管理器
  export interface MicroFrontendManager {
    // 注册微应用
    registerApp(app: MicroApp): Promise<void>;
    
    // 启动微前端
    start(options?: {
      prefetch?: boolean;
      sandbox?: boolean;
      singular?: boolean;
      fetch?: typeof window.fetch;
    }): Promise<void>;
    
    // 获取应用状态
    getAppStatus(name: string): 'NOT_LOADED' | 'LOADING' | 'NOT_BOOTSTRAPPED' | 'BOOTSTRAPPING' | 'NOT_MOUNTED' | 'MOUNTING' | 'MOUNTED' | 'UNMOUNTING' | 'UPDATING';
    
    // 手动加载应用
    loadApp(name: string): Promise<void>;
    
    // 手动挂载应用
    mountApp(name: string, props?: any): Promise<void>;
    
    // 手动卸载应用
    unmountApp(name: string): Promise<void>;
    
    // 更新应用
    updateApp(name: string, props: any): Promise<void>;
  }
  
  // 全局实例
  export const manager: MicroFrontendManager;
  export const eventBus: EventBus;
  export const globalState: GlobalState;
  export const sharedDeps: SharedDependencies;
}

// 使用示例
MicroFrontend.manager.registerApp({
  name: 'dashboard',
  version: '1.0.0',
  entry: '//localhost:3001/app.js',
  activeRule: '/dashboard'
});

MicroFrontend.eventBus.on('user-login', (user) => {
  MicroFrontend.globalState.set('currentUser', user);
});

第九部分:调试与测试 declare 声明

9.1 测试类型声明

typescript 复制代码
// tests/type-declarations.test.ts
import { expectType, expectError, expectAssignable } from 'tsd';

// 测试全局变量
expectType<string>(__VERSION__);
expectError(__VERSION__ = 123); // 应该报错,因为 VERSION 是常量

// 测试全局函数
expectType<void>(trackEvent('page_view', { path: '/' }));
expectError(trackEvent(123)); // 第一个参数应该是字符串

// 测试全局类
const widget = new ExternalWidget(document.createElement('div'));
expectType<void>(widget.render({}));
expectError(widget.render()); // 需要参数

// 测试接口扩展
const div = document.createElement('div');
expectType<HTMLDivElement>(div);
expectAssignable<HTMLElement>(div); // HTMLDivElement 应该能赋值给 HTMLElement

// 测试条件类型
type Test1 = If<true, string, number>;
expectType<string>({} as Test1);

type Test2 = If<false, string, number>;
expectType<number>({} as Test2);

// 测试品牌类型
declare const email: Email;
expectType<string>(email); // Email 可以赋值给 string
expectError<string>({} as Email); // 但不是所有 string 都是 Email

9.2 使用 TypeScript 编译器 API 验证声明

typescript 复制代码
// scripts/validate-declarations.ts
import * as ts from 'typescript';
import * as fs from 'fs';
import * as path from 'path';

interface ValidationResult {
  declarations: string[];
  errors: string[];
  warnings: string[];
  isValid: boolean;
}

class DeclarationValidator {
  constructor(private declarationDir: string) {}
  
  validate(): ValidationResult {
    const declarations = this.collectDeclarations();
    const result: ValidationResult = {
      declarations: [],
      errors: [],
      warnings: [],
      isValid: true
    };
    
    for (const declaration of declarations) {
      const validation = this.validateDeclaration(declaration);
      result.declarations.push(declaration);
      
      if (validation.errors.length > 0) {
        result.errors.push(...validation.errors);
        result.isValid = false;
      }
      
      if (validation.warnings.length > 0) {
        result.warnings.push(...validation.warnings);
      }
    }
    
    return result;
  }
  
  private collectDeclarations(): string[] {
    const files: string[] = [];
    
    const walk = (dir: string) => {
      const items = fs.readdirSync(dir);
      
      for (const item of items) {
        const fullPath = path.join(dir, item);
        const stat = fs.statSync(fullPath);
        
        if (stat.isDirectory()) {
          walk(fullPath);
        } else if (item.endsWith('.d.ts')) {
          files.push(fullPath);
        }
      }
    };
    
    walk(this.declarationDir);
    return files;
  }
  
  private validateDeclaration(filePath: string): { errors: string[]; warnings: string[] } {
    const program = ts.createProgram([filePath], {
      strict: true,
      noImplicitAny: true,
      skipLibCheck: false
    });
    
    const sourceFile = program.getSourceFile(filePath);
    const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
    
    const errors: string[] = [];
    const warnings: string[] = [];
    
    for (const diagnostic of diagnostics) {
      const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
      
      if (diagnostic.category === ts.DiagnosticCategory.Error) {
        errors.push(`Error in ${filePath}: ${message}`);
      } else if (diagnostic.category === ts.DiagnosticCategory.Warning) {
        warnings.push(`Warning in ${filePath}: ${message}`);
      }
    }
    
    return { errors, warnings };
  }
  
  generateReport(result: ValidationResult): string {
    let report = `# TypeScript 声明验证报告\n\n`;
    report += `生成时间: ${new Date().toISOString()}\n`;
    report += `验证文件数: ${result.declarations.length}\n`;
    report += `状态: ${result.isValid ? '✅ 通过' : '❌ 失败'}\n\n`;
    
    if (result.errors.length > 0) {
      report += `## 错误列表\n\n`;
      result.errors.forEach(error => {
        report += `- ${error}\n`;
      });
      report += '\n';
    }
    
    if (result.warnings.length > 0) {
      report += `## 警告列表\n\n`;
      result.warnings.forEach(warning => {
        report += `- ${warning}\n`;
      });
      report += '\n';
    }
    
    report += `## 验证的文件\n\n`;
    result.declarations.forEach(file => {
      report += `- ${file}\n`;
    });
    
    return report;
  }
}

第十部分:最佳实践与性能优化

10.1 declare 的性能影响

typescript 复制代码
// 性能优化技巧

// 1. 避免过度使用全局声明
// 不好的例子:太多全局变量
declare const A: string;
declare const B: string;
declare const C: string;
declare const D: string;
// ... 数十个全局声明

// 好的例子:使用命名空间
declare namespace Constants {
  export const A: string;
  export const B: string;
  export const C: string;
  export const D: string;
}

// 2. 避免深度嵌套的条件类型
// 不好的例子:深度递归
declare type DeepTransform<T> = 
  T extends Array<infer U>
    ? Array<DeepTransform<U>>
    : T extends object
    ? { [K in keyof T]: DeepTransform<T[K]> }
    : T;

// 好的例子:限制深度或使用简单类型
declare type ShallowTransform<T> = {
  [K in keyof T]: T[K];
};

// 3. 使用接口继承而不是交叉类型
// 不好的例子:大量交叉类型
declare type Combined = A & B & C & D & E;

// 好的例子:接口继承
declare interface Combined extends A, B, C, D, E {}

// 4. 懒加载类型声明
// 使用条件导出,只在需要时加载
declare module 'large-library' {
  export type HeavyType = /* 复杂的类型定义 */;
  
  // 提供轻量级的接口
  export interface LightInterface {
    simpleMethod(): void;
  }
  
  // 需要时再导入完整类型
  export function getHeavyType(): Promise<HeavyType>;
}

10.2 声明文件组织策略

typescript 复制代码
// 推荐的目录结构
types/
├── global.d.ts           # 全局声明
├── environment.d.ts      # 环境相关声明
├── third-party/         # 第三方库声明
│   ├── legacy-lib.d.ts
│   ├── jquery-plugins.d.ts
│   └── custom-charts.d.ts
├── extensions/          # 扩展声明
│   ├── window.d.ts
│   ├── document.d.ts
│   └── array.d.ts
├── utils/              # 工具类型
│   ├── types.d.ts
│   ├── guards.d.ts
│   └── predicates.d.ts
├── config/             # 配置类型
│   └── app-config.d.ts
└── modules/            # 模块声明
    ├── api-client.d.ts
    └── auth.d.ts

// tsconfig.json 配置
{
  "compilerOptions": {
    "typeRoots": ["./types", "./node_modules/@types"],
    "types": ["node", "express", "react"], // 显式包含的类型
    "skipLibCheck": false // 推荐关闭以检查声明文件
  },
  "include": [
    "src/**/*",
    "types/**/*" // 包含自定义声明
  ]
}

结语:declare 的艺术与科学

掌握 declare 关键字是 TypeScript 高级开发者的标志性技能。它不仅仅是技术细节,更是一种类型系统设计哲学的体现。

核心要点总结:

  1. 信任边界管理:declare 定义了 TypeScript 信任外部世界的边界
  2. 类型系统扩展:通过 declare 可以无缝集成 JavaScript 生态
  3. 架构设计工具:良好的全局类型声明是系统架构的重要组成部分
  4. 开发体验优化:为团队提供一致的类型安全和智能提示

成为 declare 大师的三个层次:

层次一:使用者

  • 理解 declare 的基本语法
  • 能使用现有的类型声明
  • 知道如何查找和安装 @types 包

层次二:设计者

  • 能为第三方库创建准确的类型声明
  • 理解声明合并和模块扩展
  • 能设计项目级的类型声明架构

层次三:架构师

  • 理解 declare 的性能影响并优化
  • 设计跨项目的类型共享方案
  • 建立类型声明的规范和流程
  • 推动类型系统的演进和优化

未来展望:

  1. 类型推导自动化:AI 辅助生成和验证声明文件
  2. 运行时类型集成:声明文件与运行时验证的深度结合
  3. 跨语言类型同步:不同编程语言间的类型声明共享
  4. 类型驱动开发:从类型声明自动生成文档、测试和实现

记住:好的类型声明不是终点,而是高质量代码的起点。通过精心设计的 declare 声明,你不仅能让 TypeScript 更好地理解你的代码,还能为整个团队建立清晰的契约和规范。

相关推荐
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
wdfk_prog9 小时前
[Linux]学习笔记系列 -- [drivers][input]input
linux·笔记·学习
崔庆才丨静觅9 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
盟接之桥10 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
崔庆才丨静觅10 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅10 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端