javascript - 如何合并打字稿模块定义
问题描述
我有一个包含自定义.d.ts
文件的 JavaScript 模块。让我们调用模块Foobar
:
foobar.js
function foobar (opts) {
this.register = plugin => {
plugin(this)
}
this.decorate = (prop, value) => {
this[prop] = value
}
return this
}
export default foobar
foobar.d.ts
export interface FoobarPlugin {
(inst: FoobarInst): void
}
export interface FoobarInst {
register(plugin: FoobarPlugin): void
decorate(prop: string, value: any): void
}
export default function foobar (): FoobarInst
我也有插件:
fuzzbuzz.js
function fuzzbuzz (inst) {
inst.decorate('fuzzbuzz', true)
}
export default fuzzbuzz
fuzzbuzz.d.ts
import { FoobarInst } from '../foobar/foobar'
export default function fuzzbuzz (inst: FoobarInst): void
我将插件加载到我的模块中:
索引.ts
import foobar from './foobar/foobar'
import fuzzbuzz from './fuzzbuzz/fuzzbuzz'
const inst = foobar()
inst.register(fuzzbuzz)
inst.fuzzbuzz // -> true
为了更新 FoobarInst 类型定义,我需要向 fuzzbuzz.d.ts 添加什么?
我尝试了以下变化:
declare module foobar {
interface FoobarInst {
fuzzbuzz: boolean
}
}
我的tsconfig.json
样子:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
}
}
感谢您提供任何帮助!
解决方案
您正在寻找的是模块扩充。我认为,import
缺少fuzzbuzz.d.ts
让 TS 识别的声明,即给定的声明扩展/增加了一个已经存在的"foobar"
模块:
fuzzbuzz.d.ts:
import { FoobarOpts } from "foobar"; // can be any import, preferrably one of "foobar"
declare module "foobar" {
// your module extensions
}
关于插件架构
插件扩展必须由编译器静态分析。这意味着,您不能在调用或通过动态导入时使 TSfoobar
增强 foobar.register(fuzzbuzz)
。
fuzzbuzz.d.ts
相反,当通过模块解析或在项目目录中自动包含 / 文件作为编译.ts
输入包含时,该模块被视为增强型。.d.ts
因此,将类型扩充放在一个模块中是有意义的foobar.register(fuzzbuzz)
,以便类型和运行时代码同步。一个最小的例子:
foobar.ts:
declare module "foobar" {
// Plugin gets the options and possibly some internal "foobar" state
type Plugin = (opts: FoobarOpts, state: {}) => void;
interface FoobarOpts {
foo: string;
bar: number;
}
export default function foobar(opts: FoobarOpts): void;
function register(plugin: Plugin): void;
}
我的插件.ts:
import { register, Plugin, FoobarOpts } from "foobar";
const fuzzBuzzPlugin: Plugin = (opt: FoobarOpts, state) => {
opt.fuzzbuzz; // fuzzbuzz available now.
};
// set type augmentation...
declare module "foobar" {
export interface FoobarOpts {
fuzzbuzz: boolean;
}
}
// ... and run-time plugin extension in one module, so they go hand in hand
register(fuzzBuzzPlugin);
客户端.ts:
import foobar from "foobar";
foobar({ bar: 42, foo: "buh", fuzzbuzz: true }); // works with fuzzbuzz
推荐阅读
- c# - 创建扩展名为“log”的日志文件
- django - HTML
- java - IOError:尝试在 java 中使用 jython 时出现 FileNotFound
- c++ - 在并行算法中使用 range::view::iota
- c# - 使用 SignalR 找不到名称为“x”的客户端方法
- javascript - 从文本字符串中选择多个关键字
- java - Java 用 ArrayList 和嵌套的 For 循环打印出一副卡片
- php - 无法通过 php 检索 jquery 设置值
- rx-java2 - RxAndroid:如何在 Observer 和 Observable 中添加额外的方法
- python - 如何根据熊猫数据框中的非连续索引列表替换值?