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
}
Quang Linh Le
  • 751
  • 1
  • 7
  • 16

1 Answers1

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 
    }
}
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • 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... – Quang Linh Le Dec 06 '17 at 10:25
  • 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 statics – Titian Cernicova-Dragomir Dec 06 '17 at 10:42
  • 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... – Quang Linh Le Dec 07 '17 at 09:43
  • 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? – Ben Mar 16 '23 at 12:21
  • @Ben that is a lint rule and it is wrong in this case. Just ignore it. Lint rules are not 100% right. – Titian Cernicova-Dragomir Mar 16 '23 at 12:55