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.
Extending Interfaces in TypeScript # Use the extends keyword to extend interfaces in TypeScript, e.g. interface Dog extends Animal {age: number;} . The extends keyword allows us to copy the members from other named types and add new members to the final, more generic interface. Copied!
In TypeScript, interfaces can also extend classes, but only in a way that involves inheritance. When an interface extends a class, the interface includes all class members (public and private), but without the class' implementations.
Extending InterfacesAn interface can extend another interface in the same way that a class can extend another class. The extends keyword is used to extend an interface, and the child interface inherits the methods of the parent interface.
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!
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With