简体   繁体   English

如何从`.d.ts`文件中的`.ts`文件导入其他类型

[英]How to import other types from `.ts` file in `.d.ts` file

I have a electron project which has strucutre:我有一个 electron 项目,它具有以下结构:

src
 - main
 - preload
   - preload.ts
   - preload.d.ts
 - render
 - shared

I want to inject some native code into my renderer code, so I use proload like this:我想在我的渲染器代码中注入一些本机代码,所以我像这样使用 proload:

// preload.ts
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron'
import { IpcChannels } from '@shared/channelNames'

contextBridge.exposeInMainWorld('api', {
    ipcSend(channel: IpcChannels, ...data: any[]) {
        ipcRenderer.send(channel, ...data)
    },
    ipcSendSync(channel: IpcChannels, ...data: any[]) {
        return ipcRenderer.sendSync(channel, ...data)
    },
    ipcOn(channel: IpcChannels, listener: (event: IpcRendererEvent, ...args: any[]) => void) {
        ipcRenderer.on(channel, listener)
    },
    ipcOnce(channel: IpcChannels, listener: (event: IpcRendererEvent, ...args: any[]) => void) {
        ipcRenderer.once(channel, listener)
    },
    ipcOff(channel: IpcChannels) {
        ipcRenderer.removeAllListeners(channel)
    }
})
// channelNames.ts
export const WINDOW_MINIMIZE = 'WINDOW_MINIMIZE'
export const WINDOW_MAXIMIZE = 'WINDOW_MAXIMIZE'
export const WINDOW_UNMAXIMIZE = 'WINDOW_UNMAXIMIZE'
export const WINDOW_CLOSE = 'WINDOW_CLOSE'
export const IS_WINDOW_MAXIMIZE = 'IS_WINDOW_MAXIMIZE'

export type IpcChannels =
    | 'WINDOW_MINIMIZE'
    | 'WINDOW_MAXIMIZE'
    | 'WINDOW_UNMAXIMIZE'
    | 'WINDOW_CLOSE'
    | 'IS_WINDOW_MAXIMIZE'

I add preload.d.ts into include array in my renderer's tsconfig.json :我在渲染器的tsconfig.json中将preload.d.ts添加到include数组中:

{
    "compilerOptions": {
        "target": "esnext",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "noFallthroughCasesInSwitch": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true,
        "jsx": "react-jsx",
        "baseUrl": ".",
        "paths": {
            "@@/*": ["../../*"],
            "@/*": ["*"],
            "@shared/*": ["../shared/*"]
        }
    },
    "include": [
        "./**/*.ts",
        "./**/*.tsx",
        "./**/*.less",
        "../shared/**/*.ts",
        "../../types/**/*.d.ts",
        "../preload/preload.d.ts"
    ]
}

Then I write preload.d.ts like this:然后我这样写preload.d.ts

import { IpcChannels } from '@shared/channelNames'

type IpcListener = (event: Electron.IpcRendererEvent, ...args: any[]) => void

interface Api {
    readonly version: string
    readonly ipcSend(channel: IpcChannels, ...data: any[]): void
    readonly ipcSendSync(channel: IpcChannels, ...data: any[]): any
    readonly ipcOn(channel: IpcChannels, listener: IpcListener): void
    readonly ipcOnce(channel: IpcChannels, listener: IpcListener): void
    readonly ipcOff(channel: IpcChannels): void
}

interface Window {
    readonly api: Api 
}

But I can't get correct type hints, window.api is any type.但我无法获得正确的类型提示, window.apiany类型。

If I remove first line import and copy IpcChannels , it works:如果我删除第一行导入并复制IpcChannels ,它可以工作:

type IpcChannels =
    | 'WINDOW_MINIMIZE'
    | 'WINDOW_MAXIMIZE'
    | 'WINDOW_UNMAXIMIZE'
    | 'WINDOW_CLOSE'
    | 'IS_WINDOW_MAXIMIZE'

type IpcListener = (event: Electron.IpcRendererEvent, ...args: any[]) => void

interface Api {
    readonly version: string
    readonly ipcSend(channel: IpcChannels, ...data: any[]): void
    readonly ipcSendSync(channel: IpcChannels, ...data: any[]): any
    readonly ipcOn(channel: IpcChannels, listener: IpcListener): void
    readonly ipcOnce(channel: IpcChannels, listener: IpcListener): void
    readonly ipcOff(channel: IpcChannels): void
}

Is there any way I can import IpcChannels rather than copy it?有什么方法可以导入IpcChannels而不是复制它? Otherwise I have to write twise if I want to add a channel name.否则,如果我想添加频道名称,我必须写两次。

https://stackoverflow.com/a/51114250/12568197 https://stackoverflow.com/a/51114250/12568197

.d.ts files are treated as an ambient module declarations only if they don't have any imports. .d.ts文件仅在没有任何导入时才被视为环境模块声明。 If you provide an import line, it's now treated as a normal module file, not the global one, so augmenting modules definitions doesn't work.如果您提供导入行,它现在被视为普通模块文件,而不是全局文件,因此扩充模块定义不起作用。

For my case it should be:就我而言,它应该是:

type IpcChannels = import('@shared/channelNames').IpcChannels 

type IpcListener = (event: Electron.IpcRendererEvent, ...args: any[]) => void

interface Api {
    readonly version: string
    readonly ipcSend(channel: IpcChannels, ...data: any[]): void
    readonly ipcSendSync(channel: IpcChannels, ...data: any[]): any
    readonly ipcOn(channel: IpcChannels, listener: IpcListener): void
    readonly ipcOnce(channel: IpcChannels, listener: IpcListener): void
    readonly ipcOff(channel: IpcChannels): void
}

interface Window {
    readonly api: Api 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM