typescript - 如何在打字稿中扩展其他模块的类型
问题描述
我正在使用 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。
我还阅读了插件类型的打字稿手册,https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-plugin-d-ts.html。
解决方案
您的示例有趣的是,访问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;
* };
* }
*/
推荐阅读
- laravel - 如何将数据从控制器发送到laravel中的rest api?
- azure-data-factory-2 - 如何在 Azure 数据工厂复制活动中使用源列对目标数据湖中的数据进行动态分区?
- r - 如何解决 r 中的“参数 x 为空”错误(Shiny Web 应用程序)
- python - 如何使用 Python Selenium 制作转发 YouTube 视频?
- node.js - 在我的 testcafe 项目中尝试 Jenkins,但构建失败
- javascript - Redux thunk 不会更改输入字段的值
- extjs - Ext js 7 现代面板.Resizer 拆分器配置
- python - 我将python转换为c编程。是否可以在另一个函数中定义一个函数?蟒蛇到C
- php - Laravel 8:试图获取非对象的属性“名称”
- python - 通过python将图表从excel复制到powerpoint