TypeScript支持 #

一、TypeScript 配置 #

1.1 安装依赖 #

bash
npm install typescript --save-dev
npm install @types/node --save-dev

# 主进程类型
npm install electron --save-dev

# 构建工具
npm install ts-node --save-dev

1.2 tsconfig.json 配置 #

json
{
    "compilerOptions": {
        "target": "ES2020",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true,
        "declaration": true,
        "declarationMap": true,
        "sourceMap": true,
        "outDir": "./dist",
        "rootDir": ".",
        "baseUrl": ".",
        "paths": {
            "@/*": ["src/*"],
            "@electron/*": ["electron/*"]
        },
        "types": ["node"]
    },
    "include": [
        "src/**/*",
        "electron/**/*"
    ],
    "exclude": [
        "node_modules",
        "dist",
        "dist-electron"
    ]
}

1.3 分离配置 #

json
// tsconfig.node.json (主进程)
{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "module": "CommonJS",
        "outDir": "./dist-electron"
    },
    "include": [
        "electron/**/*"
    ]
}

// tsconfig.web.json (渲染进程)
{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "module": "ESNext",
        "lib": ["ES2020", "DOM", "DOM.Iterable"],
        "outDir": "./dist"
    },
    "include": [
        "src/**/*"
    ]
}

二、类型定义 #

2.1 全局类型 #

typescript
// src/types/global.d.ts
declare namespace NodeJS {
    interface ProcessEnv {
        NODE_ENV: 'development' | 'production';
        ELECTRON_RENDERER_URL?: string;
    }
}

2.2 Electron API 类型 #

typescript
// src/types/electron.d.ts
import { IpcRenderer, IpcMain } from 'electron';

interface ElectronAPI {
    getAppInfo: () => Promise<AppInfo>;
    openFile: () => Promise<string | null>;
    saveFile: (content: string) => Promise<boolean>;
    onFileChanged: (callback: (data: FileChangeData) => void) => () => void;
}

interface AppInfo {
    version: string;
    platform: string;
    arch: string;
}

interface FileChangeData {
    path: string;
    type: 'created' | 'modified' | 'deleted';
}

declare global {
    interface Window {
        electronAPI: ElectronAPI;
    }
}

export { ElectronAPI, AppInfo, FileChangeData };

2.3 IPC 通道类型 #

typescript
// electron/types/ipc.ts
export interface IPCChannels {
    'app:getInfo': {
        request: void;
        response: AppInfo;
    };
    'file:open': {
        request: void;
        response: string | null;
    };
    'file:save': {
        request: { content: string };
        response: boolean;
    };
}

export type IPCChannel = keyof IPCChannels;
export type IPCRequest<T extends IPCChannel> = IPCChannels[T]['request'];
export type IPCResponse<T extends IPCChannel> = IPCChannels[T]['response'];

三、类型安全的 IPC #

3.1 主进程处理器 #

typescript
// electron/ipc/handlers.ts
import { ipcMain } from 'electron';
import { IPCChannels, IPCChannel, IPCRequest, IPCResponse } from '../types/ipc';

type IPCHandler<T extends IPCChannel> = (
    event: Electron.IpcMainInvokeEvent,
    request: IPCRequest<T>
) => Promise<IPCResponse<T>> | IPCResponse<T>;

function registerHandler<T extends IPCChannel>(
    channel: T,
    handler: IPCHandler<T>
) {
    ipcMain.handle(channel, async (event, request) => {
        return handler(event, request);
    });
}

// 使用
registerHandler('app:getInfo', async () => {
    return {
        version: app.getVersion(),
        platform: process.platform,
        arch: process.arch
    };
});

registerHandler('file:save', async (event, { content }) => {
    // 保存文件
    return true;
});

3.2 预加载脚本 #

typescript
// electron/preload.ts
import { contextBridge, ipcRenderer } from 'electron';
import { IPCChannels, IPCChannel, IPCRequest, IPCResponse } from './types/ipc';

async function invoke<T extends IPCChannel>(
    channel: T,
    request: IPCRequest<T>
): Promise<IPCResponse<T>> {
    return ipcRenderer.invoke(channel, request);
}

function on<T extends IPCChannel>(
    channel: T,
    callback: (response: IPCResponse<T>) => void
): () => void {
    const handler = (_event: Electron.IpcRendererEvent, response: IPCResponse<T>) => {
        callback(response);
    };
    
    ipcRenderer.on(channel, handler);
    
    return () => {
        ipcRenderer.removeListener(channel, handler);
    };
}

contextBridge.exposeInMainWorld('electronAPI', {
    getAppInfo: () => invoke('app:getInfo', undefined as void),
    openFile: () => invoke('file:open', undefined as void),
    saveFile: (content: string) => invoke('file:save', { content })
});

3.3 渲染进程使用 #

typescript
// src/utils/electron.ts
import { AppInfo } from '@/types/electron';

export async function getAppInfo(): Promise<AppInfo> {
    return window.electronAPI.getAppInfo();
}

export async function openFile(): Promise<string | null> {
    return window.electronAPI.openFile();
}

export async function saveFile(content: string): Promise<boolean> {
    return window.electronAPI.saveFile(content);
}

四、主进程类型 #

4.1 窗口管理类型 #

typescript
// electron/types/window.ts
import { BrowserWindow } from 'electron';

export interface WindowConfig {
    name: string;
    width: number;
    height: number;
    minWidth?: number;
    minHeight?: number;
    resizable?: boolean;
    modal?: boolean;
    parent?: string;
}

export interface WindowManager {
    create(config: WindowConfig): BrowserWindow;
    get(name: string): BrowserWindow | undefined;
    has(name: string): boolean;
    close(name: string): void;
    closeAll(): void;
}

4.2 配置类型 #

typescript
// electron/types/config.ts
export interface AppConfig {
    app: {
        name: string;
        version: string;
    };
    window: {
        width: number;
        height: number;
        x?: number;
        y?: number;
        isMaximized: boolean;
    };
    user: {
        theme: 'light' | 'dark';
        language: string;
    };
}

export type PartialAppConfig = PartialDeep<AppConfig>;

interface PartialDeep<T> {
    [P in keyof T]?: T[P] extends object ? PartialDeep<T[P]> : T[P];
}

五、渲染进程类型 #

5.1 Vue 组件类型 #

typescript
// src/types/vue.d.ts
import { DefineComponent } from 'vue';

declare module '*.vue' {
    const component: DefineComponent<{}, {}, any>;
    export default component;
}

5.2 Store 类型 #

typescript
// src/stores/app.ts
import { defineStore } from 'pinia';

interface AppState {
    theme: 'light' | 'dark';
    sidebarOpen: boolean;
    user: User | null;
}

interface User {
    id: string;
    name: string;
    email: string;
}

interface AppActions {
    setTheme: (theme: 'light' | 'dark') => void;
    toggleSidebar: () => void;
    setUser: (user: User | null) => void;
}

export const useAppStore = defineStore<string, AppState, {}, AppActions>('app', {
    state: () => ({
        theme: 'light',
        sidebarOpen: true,
        user: null
    }),
    
    actions: {
        setTheme(theme) {
            this.theme = theme;
        },
        
        toggleSidebar() {
            this.sidebarOpen = !this.sidebarOpen;
        },
        
        setUser(user) {
            this.user = user;
        }
    }
});

六、构建配置 #

6.1 Vite 配置 #

typescript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import electron from 'vite-plugin-electron';
import path from 'path';

export default defineConfig({
    plugins: [
        vue(),
        electron([
            {
                entry: 'electron/main.ts',
                vite: {
                    build: {
                        outDir: 'dist-electron',
                        rollupOptions: {
                            external: ['electron']
                        }
                    }
                }
            },
            {
                entry: 'electron/preload.ts',
                vite: {
                    build: {
                        outDir: 'dist-electron'
                    }
                }
            }
        ])
    ],
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './src')
        }
    }
});

6.2 package.json scripts #

json
{
    "scripts": {
        "dev": "vite",
        "build": "vue-tsc --noEmit && vite build && electron-builder",
        "typecheck": "vue-tsc --noEmit"
    }
}

七、最佳实践 #

7.1 类型检查清单 #

markdown
- [ ] 配置 tsconfig.json
- [ ] 定义全局类型
- [ ] IPC 通道类型化
- [ ] 组件类型定义
- [ ] Store 类型定义
- [ ] 启用严格模式

7.2 类型导入 #

typescript
// 使用 type 关键字导入类型
import type { AppInfo, FileChangeData } from '@/types/electron';

// 或使用类型重导出
export type { AppInfo, FileChangeData } from '@/types/electron';

八、总结 #

8.1 核心要点 #

要点 说明
配置分离 主进程和渲染进程分离配置
类型定义 全局类型和模块类型
IPC 类型 类型安全的进程间通信
严格模式 启用 TypeScript 严格检查

8.2 下一步 #

现在你已经掌握了 TypeScript 支持,接下来让我们学习 实战案例,深入了解 Electron 应用的完整开发流程!

最后更新:2026-03-28