How to extend an interface declared in an external library d.ts?

I installed the knockout definitions using the documented method like this.

npm install @types/knockout

It works nicely, I could import it like this anywhere.

import * as ko from "knockout";

However, I'm stuck with extending KnockoutStatic interface with some custom stuff. I'm trying to migrate a <reference ... /> and namespace based huge TS application to use modules. Before, I easily declared the extension interface anywhere and the declarations got merged. Let's say my extension looks like this.

interface KnockoutStatic {
  doSomething(): void;
}

I tried to create a KnockoutExtensions.d.ts file where I declared it like this.

import "knockout";

declare module "knockout" {
  export interface KnockoutStatic {
    doSomething(): void;
  }
}

But when I import both knockout and my extension somewhere, TS still cannot resolve the doSomething calls.

import * as ko from "knockout";
import "./KnockoutExtensions";

ko.doSomething(); // error

What is the proper method of extending library interfaces using TypeScript 2.0 and the new d.ts subsystem?

I'm using Visual Studio 2015 Update 3 with TypeScript 2.0 installed.

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

Example: create knockout-extension.d.ts file

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

declare module 'knockout' {

  export interface CustomType {

    customField: string;

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

  namespace customNamespace {

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

  // NOTE: extending existing interface
  export interface KnockoutStatic {
    customMethod(): void;
  }
}

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

Use the newly defined types from the extended module.

// one way
import { CustomType } from 'knockout';

const foo: CustomType;

// second way
import * as kc from 'knockout';

const foo: kc.CustomType;
const bar: kc.customNamespace.AnotherCustomType;

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

Cheers!

Extend external modules declared in @types npm dependency , For the purposes of this article, “declaration merging” means that the compiler merges The compiler will issue an error if the interfaces both declare a non-​function already exists with the given name, it is further extended by taking the existing observable.ts export class Observable<T> { // implementation left as an  Except this does not extend the type information. I cannot just do something like: export interface lib.MyCoolFunctions { extFunc( whatever ) { } } (trust me, I've tried; you may start laughing now :-) So instead, in order to make my library extensible, I have to split it into declaration (in the form of .d.ts) and implementation:

The problem is that knockout typing file uses the export = syntax and it's not "augmentation friendly". See this as a reference.

The simplest solution for me was to wrap the extensions in declare global { } as knockout typing file declares everything in global scope.

declare global {
  interface KnockoutStatic {
    doSomething(): void;
  }
}

Declaration Merging · TypeScript, and errors) while using external library dependencies in my project. You can find this in the empty-types.d.ts file in the project: declare module 'classnames' { const noTypesYet: any; export default noTypesYet; } The above describes a class that extends a React component which has four properties:. One of the biggest pain points I’ve faced with TypeScript is using it in strict mode (without disabling several warnings and errors) while using external library dependencies in my project. In these circumstances, you have to add your own custom type definitions for the libraries.

You need to create your interface outside of your module. Do not declare it with export.

module example { //...do stuff }

interface KnockoutStatic { doSomething(): void; }

You can your on file, where you add your interface extensions to keep it clean.

TypeScript: Adding Custom Type Definitions for Existing Libraries , e.g. the following is good as people can customize foo further in other library definitions. // Usage when declaring an external module declare module 'foo' { var foo: NodeJS.Foo; export = foo; }. Extending built-in types For adding members to instances of native types there are relevant interfaces in available in lib.d.ts  there are two options, mainly depending on how you expect your users to reference the interface; declare the extension in a non-module global file, and add a /// reference to it from your .d.ts; this way you are telling the compiler that your .d.ts file depends on this other file that changes the global scope.

I found that winston has the same problem, using the export = syntax. I found this page helpful when it showed that react did the same thing: https://www.credera.com/blog/technology-solutions/typescript-adding-custom-type-definitions-for-existing-libraries/.

The solution they recommended, which I found worked is this:

import 'react';

declare module 'react' {
    interface OlHTMLAttributes<T> {
        type?: "1" | "a" | "A" | "i" | "I";
    }
}

Simply importing the module, and then declaring it allows any interfaces in this declaration block to extend the existing ones and in other parts of you code you can go on using the interface as you normally would; i.e. you would still import react or winston or knockout and you'd see these new interface members. You don't have to start referencing a custom interface or anything like that.

Best practices, typings/bunyan/bunyan.d.ts" /> declare module Express { export interface Request tl;dr; How to extend interface definition with external module definitions. To merge the namespaces, type definitions from exported interfaces declared in each namespace are themselves merged, forming a single namespace with merged interface definitions inside. To merge the namespace value, at each declaration site, if a namespace already exists with the given name, it is further extended by taking the existing namespace and adding the exported members of the second namespace to the first.

Extending typescript interface - interface - html, In this post we talked about merging interfaces with interfaces. Module augmentation helps us to extend functionalities to third party libraries we may not have we want to add to the extended class. index.ts. declare module "./pet" { interface Pet { age: number; walk(location: string); } } We'd like to help. Interfaces Extending Classes # When an interface type extends a class type it inherits the members of the class but not their implementations. It is as if the interface had declared all of the members of the class without providing an implementation. Interfaces inherit even the private and protected members of a base class.

Module Augmentation in TypeScript, How can I export an interface from d.ts file; so that, modules can import the type definition? I have written type definitions for an external library by creating a X.d.​ts file. <reference types="react" /> declare module '@mycompany/styled-library' What would be the most elegant and efficient way to implement a type of Map  make sure the file that contains the module augmentation is itself a module (i.e. includes at least one top-level import or export). so this should work: import * as estree from 'estree' ; declare module 'estree' { interface MyAddon { } } mhegazy added the Question label on Sep 12, 2016

How can I export an interface from d.ts file; so that, modules can , Library packages often include typings in .d.ts files; see examples in If don't add the interface for the script-defined extension, your IDE shows an error:. In a number of places we are using a third party typing for some interface that declares one of it's sub properties or methods as as type any and we would like to create more strongly typed interfaces based on these. For example the angular.ui.IStateService interface has a property called current which in turn has a property called data for

Comments
  • This didn't work, this worked only when I didn't use modules, but pure namespaces.