1

I am new in TypeScript, could anyone help me to figure it out the best practices with implementing interface in class? Because when I tried to following the Docs (Class Heritage), I caught in some problem like so:

  1. declare interface
interface Notification {
    message: string;
    send(msg?: string): void;
}
  1. implements interface in class with constructor()
class Notifier implements Notification {
    constructor(
        public message: string,
    ){}

    send(customMsg?: string): void {
        if (customMsg) {
            console.log(customMsg);
        } else {
            console.log(this.message);
        }
    }
}
  1. example, using class
const hello = new Notifier("hello");
hello.send();
hello.send("Alert!");

Unfortunately, I found an error message like the following:

Class 'Notifier' incorrectly implements interface 'Notification'. Type 'Notifier' is missing the following properties from type 'Notification': actions, badge, body, data, and 19 more.

Could anyone tell me what is my wrong? Thanks in advance!

1
  • 1
    Aside: I am changing your message property from private to public or you will hit a new error after you resolve the current one. Since you are not asking about private vs public, this issue is therefore outside the scope of the question and we should clear things up by using public, as my answer below does. Commented Apr 27, 2021 at 15:47

1 Answer 1

1

Your problem is that the TypeScript standard library already includes a globally-scoped interface named Notification corresponding to the Notification interface from the Web Workers API. Because of this, your Notification interface definition is just merging additional members into it. This is obviously not what you intend.

The fix here is either to rename your interface to something else like MyNotification, or create a module or namespace that creates a new naming scope for your code:

// use of "export" makes your code a module
export interface Notification { 
    message: string;
    send(msg?: string): void;
}

or

namespace MyNamespace {
  export interface Notification {
    message: string;
    send(msg?: string): void;
  }
}

And then you should be able to refer to it later. If you use the namespace approach, you'll get this:

class Notifier implements MyNamespace.Notification {
  constructor(
    public message: string, 
  ) { }

  send(customMsg?: string): void {
    if (customMsg) {
      console.log(customMsg);
    } else {
      console.log(this.message);
    }
  }
}


const hello = new Notifier("hello");
hello.send();
hello.send("Alert!");

Which works as desired.

Playground link to code

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you so much! I don't realize it and it is work when I change the name of that interface to MyNotification.
But, how about using private access modifiers in constructor while implementing an interface? Since in your example, we must change message property to public.
That's a different question, isn't it? If I have a MyNotification object, I should be allowed to access its message property, according to your interface definition. If Notifier makes message a private property, then I can't do that. Just like you couldn't make it a number if it is supposed to be a string. Therefore, making it private causes Notifier not to be a valid MyNotification. You can have private properties in Notifier, but they cannot conflict with properties from MyNotification.
A comment section is not a good place to discuss this subsequent issue. You should consider doing more research to look for existing questions like this one, and if you can't find an answer, consider posting a new question. Good luck!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.