Electron preload.ts 类型无法自动推导的解决方案
在 Electron 中通过 contextBridge.exposeInMainWorld() 暴露 API:
javascript
// preload.ts
import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('electron', {
puppeteer: () => ipcRenderer.invoke('puppeteer'),
db: () => ipcRenderer.invoke('db'),
});
Renderer 中调用:
javascript
await window.electron.puppeteer();
TypeScript 会报错:
rust
Property 'electron' does not exist on type 'Window & typeof globalThis'
原因是:
contextBridge.exposeInMainWorld() 只是在运行时向 window 注入对象,TypeScript 并不会根据 preload.ts 自动推导出:
javascript
window.electron
的类型。
因此需要手动定义类型声明,并让 preload.ts 和 Renderer 共用同一套类型。
1. 定义 Electron API 类型
创建:
bash
src/types/electron.ts
typescript
export interface ElectronAPI {
puppeteer(): Promise<void>;
db(): Promise<unknown>;
}
以后所有暴露给 Renderer 的 Electron API,都统一维护在这里。
2. preload.ts 使用同一个类型
typescript
import { contextBridge, ipcRenderer } from 'electron';
import type { ElectronAPI } from './types/electron';
const electronAPI: ElectronAPI = {
puppeteer: () => ipcRenderer.invoke('puppeteer'),
db: () => ipcRenderer.invoke('db'),
};
contextBridge.exposeInMainWorld('electron', electronAPI);
这样 preload.ts 本身也会受到 TypeScript 类型检查。
例如 ElectronAPI 中声明了:
javascript
puppeteer(): Promise<void>;
但 electronAPI 中漏掉了这个方法,TypeScript 会直接提示错误。
这样可以避免接口类型和实际 preload 实现不一致。
3. 给 window.electron 增加全局类型
创建:
bash
src/types/global.d.ts
typescript
import type { ElectronAPI } from './electron';
declare global {
interface Window {
electron: ElectronAPI;
}
}
export {};
之后 Renderer 中就可以直接使用:
javascript
await window.electron.puppeteer();
const result = await window.electron.db();
同时也会有完整的 IDE 自动补全和 TypeScript 类型检查。