Utvid importert TypeScript-grensesnitt


Jeg bruker en pakke — ko-component-router — med følgende (forkortede) typedefinisjoner...

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;
}

På forbrukersiden blir det registrert mellomvare som kan legge til egenskaper til konteksten som sendes inn i visningskomponenten, som sådan...

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


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

Som forventet, kaster kompilatoren en Property 'someProperty' does not exist on type 'IContext'-feil.

Basert på dokumentasjonen om deklarasjonssammenslåing, forsøkte jeg å legge til følgende for å gjøre kompilatoren oppmerksom på denne nye egenskapen...

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

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

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

Men den samme feilen kastes. Jeg har prøvd omtrent alt jeg kan komme på, men jeg klarer ikke å få kompilatoren til å bli klar over denne nye egenskapen uten å fullstendig re-implementere typedefinisjonene i prosjektet mitt, noe som åpenbart er langt fra ideelt.

Er dette mulig, og hvis så, hvor gjør jeg feil?

Svar #1

Som nevnt i cartants kommentar, fungerer ikke modulforsterkning for klasser og grensesnitt som eksporteres "indirekte" - dette er et kjent problem.

Det fungerer hvis du utvider den indre modulen der IContext er definert:

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

Dessverre introduserer alle som legger til utvidelser på denne måten en avhengighet av den interne strukturen til biblioteket ditt.

Også, med denne utvidelsen kompilerer ikke lenger class Context:

feil TS2420: Klassen 'Context' implementerer feilaktig grensesnittet 'IContext'. Egenskapen 'someProperty' mangler i typen 'Context'.

Så hvis du legger til egenskaper til grensesnitt som implementeres av noen klasser, må disse egenskapene være valgfrie:

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

Relaterte artikler