简体   繁体   中英

Extend a namespace from package typings

I'm trying here to extend a namespace from package typings, @typings/fullcalendar .

/// <reference path="./types/fullcalendar" />

import * as fullcalendar from 'fullcalendar';
import { TimeGrid } from 'fullcalendar';

// TimeGrid and fullcalendar.views are used then

Originals typings can be seen here .

And fullcalendar-custom.d.ts is

import * as FC from 'fullcalendar';

export as namespace FC;

declare class TimeGrid { prepareHits() }

declare let views: any;

This results in type errors, so it is obvious that fullcalendar namespace wasn't extended properly:

TS2305: Module '".../node_modules/@types/fullcalendar/index"' has no exported member 'TimeGrid'.

TS2339: Property 'views' does not exist on type 'typeof ".../node_modules/@types/ fullcalendar/index"'.

How should this be done the right way?

Can reference directive be avoided here, considering that types directory is specified in typeRoots ?

The application is bundled with Webpack and awesome-typescript-loader, so the behaviour may differ from other compilation methods. At some point types seemed to be ok in IDE inspections (WebStorm) but still got type errors on compilation.

We can import a namespace in a non-declaration .ts , and export it again as a extended type:

// custom-fc.ts : enhances declaration of FC namespace
import * as origFC from "fullcalendar";

declare namespace Complimentary {
    class TimeGrid {
        prepareHits(): void;
    }
    let views: any;
}

// apply additional types to origFc and export again
export const FC: (typeof Complimentary & typeof origFC) = origFC as any;

// use-fc.ts : consumer of extended declaration
import { FC } from "./custom-fc";

console.log(FC.TimeGrid);
console.log(FC.views);

(This somehow differs from your scenario, in that I'm using @types/ packages and webpack ts-loader , but you should be able to do something similar.)

You can easily extend the 'fullcalendar' or any other TypeScript namespace.

Example: create fullcalendar-extension.d.ts file

/// <reference path="<path-to-typings-dir>/fullcalendar/index.d.ts" />

declare module 'fullcalendar' {

  export interface TimeGrid {

    customField: string;

    customMethod(arg1: number, arg2: boolean): boolean;

    prepareHits();
  }

  namespace customNamespace {

    export interface AnotherTimeGrid {
      customField1: string;
      customField2: boolean;
    }
  }
}

Note: ensure that this file is picked-up by the TypeScript compiler.

Use the newly defined types from the extended module.

// one way
import { TimeGrid } from 'fullcalendar';

const timeGrid: TimeGrid;

// second way
import * as fc from 'fullcalendar';

const timeGrid: fc.TimeGrid;
const anotherTimeGrid: fc.customNamespace.AnotherTimeGrid;

For more info on modules and namespaces you can check TypeScript documentation on Modules and Namespaces and using them together .

Cheers!

Using latest TypeScript v4, when I had issues with combining external files and libs with Svelte I did this:

// root/my-declarations.d.ts

import { SomeNameSpace as SomeNameSpaceOriginal} from '../../any-relative-path/to/ts-file';
import {SvelteComponentDev} from 'svelte/internal';

declare namespace SomeNameSpaceExtended {
    function setValue(value:any):any
    let UI:SvelteComponentDev
    let abc:string
}

declare global {
    //this will add new items to top-level (root)
    //note: in my case, only importing "as SomeNameSpaceOriginal" gave me correct typing later using our new extended global SomeNameSpace
    let SomeNameSpace: typeof SomeNameSpaceOriginal & typeof SomeNameSpaceExtended;

    //this will add new items to window:
    interface Window {
        elementInside:'window.elementInside'
    }
}

Upvoted Answer in combination with https://stackoverflow.com/a/63973683 gives most understanding about how to extend things around.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM