Typescript declaration: Merge a class and an interface
Asked Answered
T

1

8

I have two models Model and its subclass ClientModel an ambient module. Now I want to declare a set of attributes of ClientModel from an interface so called Client. How can I do it? I can imagine something like this:

interface Client {
    name: string;
    email: string;
}

declare class ClientModel extends Model implements Client {
    // with name and email here without redeclare them
}
Thereinafter answered 6/12, 2017 at 9:34 Comment(0)
D
21

You can use declaration merging. If the class and the interface are declared in the same namespace/module and have the same name, they will be merged into a single class type.

interface ClientModel {
    name: string;
    email: string;
}

class ClientModel extends Model  {
    m() {
        this.email //Valid 
    }
}

If you cannot change the interface or is declared in another namespace and you can't move it you can inherit from it in the merged interface:

interface Client {
    name: string;
    email: string;
}

interface ClientModel extends Client {}
class ClientModel extends Model  {
    m() {
        this.email //Valid 
    }
}
Dibbrun answered 6/12, 2017 at 9:52 Comment(5)
Hello @Titian, let me know if I should ask a new question. Is there a way I can add a static property to the base Model. I got a TS2300 when I try to merge the declaration...Thereinafter
When do you get the error? when trying to add a static property ? Merging only works in some cases, interface + class is one, class + class will not work, and interfaces can't have staticsDibbrun
Exactly, The class (Model) is from an ambient module that I do not control. I can easily merge with a set of instance properties (e.g. instance.name) the way you show me but not for a static one (e.g Model.toJSON().) You said that "class + class will not work" which is the case...Thereinafter
For the second approach, it works fine, but I get this linter error: "An interface declaring no members is equivalent to its supertype.eslint@typescript-eslint/no-empty-interface". Any idea how to address this?Persas
@Persas that is a lint rule and it is wrong in this case. Just ignore it. Lint rules are not 100% right.Dibbrun

© 2022 - 2024 — McMap. All rights reserved.