【问题标题】:Augment imported typescript interface增强导入的 typescript 接口
【发布时间】:2018-04-05 17:08:30
【问题描述】:

我正在使用一个包 — ko-component-router — 具有以下(精简)类型定义...

index.d.ts

export { IContext, Context } from './context';
export { Router } from './router';

context.d.ts

export interface IContext {
    $root: IContext;
    $child: IContext;
    $children: IContext[];
    $parent: IContext;
    $parents: IContext[];
    router: Router;
    route: Route;
    params: {
        [k: string]: any;
    };
    path: string;
    pathname: string;
    base: string;
    canonicalPath: string;
}
export declare class Context implements IContext {
  // ...
}

router.d.ts

import { IContext } from './context';
export declare type Middleware = (ctx: IContext, done?: () => any) => {
    beforeRender?: (done?: () => void) => Promise<any> | void;
    afterRender?: (done?: () => void) => Promise<any> | void;
    beforeDispose?: (done?: () => void) => Promise<any> | void;
    afterDispose?: (done?: () => void) => Promise<any> | void;
};
export declare class Router {
    static use(...fns: Middleware[]): void;
}

在消费者端,注册中间件可以将属性添加到传递到视图组件的上下文中,因此......

import { Router } from 'ko-component-router'


Router.use((ctx) => ({
    beforeRender() {
        ctx.someProperty = 'foo'
    }
}))

正如预期的那样,编译器抛出了Property 'someProperty' does not exist on type 'IContext' 错误。

根据declaration merging 上的文档,我尝试添加以下内容以使编译器了解这个新属性...

import { Router } from 'ko-component-router'

declare module 'ko-component-router' {
    interface IContext {
        someProperty: string
    }
}

Router.use((ctx) => ({
    beforeRender() {
        ctx.someProperty = 'foo'
    }
}))

但是抛出了同样的错误。我已经尝试了几乎所有我能想到的东西,但是如果不完全重新实现我的项目中的类型定义,我无法让编译器知道这个新属性,这显然远非理想。

这可能吗?如果可以,我会误入歧途吗?

【问题讨论】:

标签: typescript


【解决方案1】:

正如 carant 的评论中提到的,模块扩充不适用于“间接”导出的类和接口 - this is a known issue

如果您扩充定义 IContext 的内部模块,它会起作用:

declare module 'ko-component-router/context' {
    export interface IContext {
        someProperty: string
    }
}

不幸的是,任何以这种方式添加扩充的人都会引入对库内部结构的依赖。

此外,有了这个扩充,class Context 不再编译:

错误 TS2420:“上下文”类错误地实现了接口 'IContext'。 “上下文”类型中缺少属性“someProperty”。

所以如果你给某些类实现的接口添加属性,这些属性必须是可选的:

declare module 'ko-component-router/context' {
    export interface IContext {
        someProperty?: string
    }
}

【讨论】:

  • 刚刚得出这个结论,但这绝对是它。绕过讨厌的declare module 'ko-component-router/dist/context',将任何预期会被扩充的接口移动到索引文件本身中。
  • 重要提示declare module thingdeclare module "thing" 不同。让我困惑了一段时间。 (带引号时,它会尝试将模块解析为现有模块匹配;不带引号时,它假定您正在声明一个全新的模块/命名空间)
猜你喜欢
  • 1970-01-01
  • 2017-12-07
  • 2015-08-23
  • 2021-10-26
  • 2017-05-31
  • 1970-01-01
  • 2017-04-17
  • 2017-10-27
  • 1970-01-01
相关资源
最近更新 更多