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.