Search code examples
reactjstypescriptpluginstypescript-typingstheia

How to re-export React in d.ts?


I am working on an plugin system like https://github.com/eclipse-theia/theia/blob/master/packages/plugin/src/theia.d.ts.

My @my-scope/plugin package provide type definitions. And the plugin context is passed to the plugin start function like this when plugin is loaded:

// import React from 'react' // Should NOT import react in a plugin
import * as  from '@my-scope/plugin';

export function start(ctx: my.PluginContext) {
    // Dialog and Button component should have correct 
    const { Dialog, Button } = ctx.ui; types

    ctx.registerDialog('dialog1', () => {
      // onCustomEvent should be auto-suggested
      return <Dialog onCustomEvent={...}><Button onClick={...}>OK</Button></Dialog>;
    });

}

(To make JSX working, I can set jsxFactory to ctx.React.createElement in tsconfig.json as a workaround.)

Plugins are not isolated in iframe or web worker, but sharing the globals with it's host (for legacy reason). The plugin also need to create React components using A React UI library. So I have to expose React and UI library in the plugin context cause there should have only one React in an app and all plugin sharing the common UI library (and other library like axios).

My question is how to re-export React and UI library in the plugin context definition so that plugin can access correct types and have auto-suggestion in JSX.


export module "@my-scope/plugin" {
  export interface PluginContext {
    React: ??? // how to re-export React types here
    ui: ???; // how to re-export UI library types here
    registerDialog(dialogName: string, () => JSX.Element);
  }
}

Solution

  • Luckily, When I browser @rollup/plugin-typescript source, I found following code which solved my question:

    typescript?: typeof import('typescript');
    

    In my case

    export module "@my-scope/plugin" {
      export interface PluginContext {
        React: typeof import('react');
        ui: typeof import('some-ui-lib');
        registerDialog(dialogName: string, () => JSX.Element);
      }
    }