【问题标题】:How can I extend other module's types in typescript如何在打字稿中扩展其他模块的类型
【发布时间】:2021-03-13 07:25:04
【问题描述】:

我正在使用 ts 编写一个库,在尝试扩展核心模块类型时遇到了一些麻烦。这是项目结构。

- src
  - core
    - core.ts
  - plugins
    - insert
      - index.ts

core.ts中的代码

export interface Commands {}

export class Core {
  commands: Commands;

  constructor() {
    this.commands = {};
  }

  registerCommands(name: string, func: any) {
    // @ts-ignore
    this.commands[name] = func;
  }
}

insert/index.ts中的代码

import { Core } from "../../core/core";

export class InsertPlugin {
  constructor(core: Core) {
    core.registerCommands("insert", this.insert.bind(this));
  }

  insert(value: string) {
    console.log("insert " + value);
  }
}

InsertPlugin 使用core.registerCommands 将命令insert 注册到核心。

我的问题是使用我的库的人如何获取insert 命令的类型。例如

// assume the name of the library is core
import { createCore } from 'core'

const core = createCore()
// How can i get types for insert method
core.commands.insert()

我已经为上面的代码创建了一个完整的演示,https://github.com/clinyong/ts-extends-core-commands

我还阅读了插件类型的 typescript 手册,https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-plugin-d-ts.html

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您的示例的有趣之处在于,访问core.commands.insert() 仅在您创建new InsertPlugin(core) 实例之后才有效(您在示例中没有这样做)。

    鉴于此,如果您要使用具有断言返回类型的函数而不是类,则实际上可以对这个要求进行编码。

    insert/index.ts:

    import { Core } from "../../core/core";
    
    function registerInsertPlugin(core: Core): asserts core is (Core & {
      commands: {
        insert: typeof insert
      }
    }) {
    
      const insert = (value: string) => {
        console.log("insert " + value);
      }
    
      core.registerCommands("insert", insert);
    }
    

    那么你可以这样使用它:

    import { createCore } from 'core'
    import { registerInsertPlugin } from 'insert'
    
    const core = createCore();
    registerInsertPlugin(core);
    core.commands.insert('hello world');
    

    忘记调用registerInsertPlugin会导致有效类型错误:

    
    import { createCore } from 'core'
    
    const core = createCore();
    core.commands.insert('hello world');
    // ^ Property 'insert' does not exist on type 'Commands'
    

    除此之外,您还可以创建多个“插件”,每个插件都将使用相关类型扩展core.commands

    const core = createCore();
    registerInsertPlugin(core);
    registerUpsertPlugin(core);
    core.commands.insert('hello world');
    core.commands.upsert("hello world");
    
    /* Resulting Type:
     * const core: Core & {
     *     commands: {
     *         insert: (value: string) => void;
     *     };
     * } & {
     *     commands: {
     *         upsert: (value: string) => void;
     *     };
     * }
     */
    

    【讨论】:

      猜你喜欢
      • 2016-07-04
      • 2021-02-03
      • 2018-04-18
      • 2014-06-11
      • 2019-06-20
      • 2018-02-11
      • 2020-08-18
      • 1970-01-01
      • 2018-01-10
      相关资源
      最近更新 更多