Just like object-oriented languages such as Java and C#, TypeScript classes can be extended to create new classes with inheritance, using the keyword extends . In the above example, the Employee class extends the Person class using extends keyword.
The extends keyword allows us to copy the members from other named types and add new members to the final, more generic interface.
declare class is for when you want to describe an existing class (usually a TypeScript class, but not always) that is going to be externally present (for example, you have two . ts files that compile to two . js files and both are included via script tags in a webpage).
If you don't control the original definition file, and can't make adjustments to it, then unfortunately, what you're trying to do isn't supported currently in TypeScript. An interface
in TypeScript is the only construct that allows reasonable extensions as it is only a compile-time/syntax check and not a run-time operation.
You cannot extend a class
in TypeScript with new functionality using only TypeScript (and expecting code-completion/Intellisense to work as expected). You could of course add the functions to the prototype
for the CircleMarker
class, but they would be unavailable to Intellisense and would fail to compile unless you use a type assertion.
Instead of using any
, you should be able to use an interface
with the type assertion:
declare module L {
export interface CircleMarkerEx {
bindLabel(name: string, options: any): CircleMarker;
}
}
Then:
var cm = <L.CircleMakerEx> circle.bindLabel("name", {});
Thankfully, it doesn't add any run-time overhead, just a bit of extra typing (pun intended!).
There have been suggestions for things like "mix-ins" on CodePlex, but they have not been implemented. Even the mix-in suggestions would not be entirely straightforward to use, and wouldn't work well for libraries that weren't entirely written in TypeScript (as it would be too easy to have JavaScript code that simply could not be safely constructed for example with a mix-in).
You can't do that with the class
keyword. There is a feature request you can vote on here : https://typescript.codeplex.com/workitem/917
You can however mimic classes using interfaces
as shown in the workaround (https://typescript.codeplex.com/workitem/917) for the issue. In your case
declare module L {
function circleMarker(latlng: LatLng, options?: PathOptions): CircleMarker;
declare var CircleMarker: CircleMarkerStatic;
export interface CircleMarkerStatic{
new (latlng: LatLng, options?: PathOptions): CircleMarker;
}
export interface CircleMarker {
setLatLng(latlng: LatLng): CircleMarker;
setRadius(radius: number): CircleMarker;
toGeoJSON(): any;
}
}
and extend it
declare module L {
export interface CircleMarker {
bindLabel(name: string, options: any): CircleMarker;
}
}
This is what I tried and it feels relatively comfortable for me
declare module L {
export class CircleMarkerEx {
constructor(source: CircleMarker);
public bindLabel(name: string, options: any): CircleMarker;
}
export function ex(cm: CircleMarker): CircleMarkerEx;
}
where CircleMarkerEx
and ex
can be defined as
class CircleMarkerExtender extends CircleMarker {
public b() {
return `${this.a()} extended`;
}
}
CircleMarker.prototype = Object.create(CircleMarkerExtender.prototype);
CircleMarker.prototype.constructor = CircleMarker;
export function ex(cm: CircleMarker) {
return cm as CircleMarkerExtender;
}
then
let cm = ex(circle).bindLabel("name", {});
but it is still a little strange
Is this possible?
declare module L {
export class MyCircleMarker extends CircleMarker{
bindLabel(name: string, options: any): CircleMarker;
}
}
And then define your CircleMarker instances as MyCircleMarker
Edit: this answer is off topic. It talks about interfaces and not classes like asked
I didn't have any problem extending a TypeScript (v3.6) external type definition.
// File types/googlemaps-marker-hello.d.ts or
// whatever file name you like, it doesn't matter
declare namespace google.maps {
interface Marker {
hello: string;
}
}
// Later on inside src/MyCode.ts
const marker = new google.maps.Marker();
marker.hello = 'Hello, World!';
You don't have to modify your tsconfig.json: it just works.
See https://github.com/DefinitelyTyped/DefinitelyTyped/blob/edb4917e1bbd0d860b51e7806775cb505f858e36/types/webpack-dev-server/index.d.ts#L206-L211:
declare module 'webpack' {
interface Configuration {
devServer?: WebpackDevServer.Configuration;
}
}
webpack-dev-server type definition extends webpack type definition. If you use @types/webpack and not @types/webpack-dev-server you won't have the devServer
property.
declare namespace NodeJS {
interface Global {
hello: string;
}
}
global.hello = 'Hello, World!';
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