What is the process for applying an interface to a class?

I have created a unique custom class named GreetingsManager. It includes a special method named loadData which accepts an object as input and assigns all properties of that object to the class instance. To ensure proper type checking, I have implemented an interface called GreetingsInterface for both the class and the object parameter.

interface GreetingsInterface { 
    message: string;
    name: string;
    lastName: string;
    age: number; 
}
class GreetingsManager implements GreetingsInterface {
    constructor(message: string) {
        this.message = message;
    }
    loadData(obj: object) { 
        Object.assign(this, obj)
        return this;
    }
    greet() {
        return "Hello, " + this.message;
    }
}

let data: GreetingsInterface = {
    message: 'Hi',
    lastName: 'Smith',
    name: 'John',
    age: 25
}
let greetings = new GreetingsManager('Bonjour').loadData(data);

let button = document.createElement('button');
button.textContent = "Display Greetings";
button.onclick = function() {
    console.log(greetings)
}

document.body.appendChild(button);

However, upon compilation, an error is thrown stating that GreetingsManager does not contain a property named 'message'.

Answer №1

An interface serves to outline the structure of the data it pertains to, without prescribing how it is carried out. By defining that Greeter follows the design of a GreeterInterface, TypeScript acknowledges the shape but not the specific implementation. There are various ways to implement a single shape, and TypeScript remains neutral regarding the desired implementation. For instance:

interface GreeterInterface { 
    greeting: string;
    name: string;
    lastname: string;
    age: number; 
}

class Greeter implements GreeterInterface{
    greeting: "Bonjour" | "Hola";
    name: string;
    lastname: string;

    private _age: number;

    get age(): number {
        return this._age;
    }

    set age(value: number) {
        this._age = value;
    }

    constructor(message: "Bonjour" | "Hola") {
        this.greeting = message;
    }
    fromJson(obj: object) { 
        Object.assign(this, obj)
        return this;
    }
    greet() {
        return "Bonjour, " + this.greeting;
    }
}

The definition outlined by GreeterInterface indicates that the greeting field should be a string, yet Greeter opts for a more specific type, which is acceptable. Additionally, while age could simply be a field, Greeter chooses to use getter/setter methods, demonstrating another valid approach.

Answer №2

After much investigation, I finally found the solution. I made a crucial adjustment to the constructor by replacing fromJson with

constructor(obj: GreeterInterface)
. This change was necessary because of an issue with Louis' solution that caused TypeScript to throw an error stating "has no initializer and is not definitely assigned in the constructor."

interface GreeterInterface {
    greeting: string;
    name: string;
    lastname: string;
    age: number;
}

class Greeter implements GreeterInterface{

    age: number;
    greeting: string;
    lastname: string;
    name: string;

    constructor(obj: GreeterInterface) {
        this.lastname =  obj.lastname;
        this.greeting =  obj.greeting;
        this.name =  obj.name;
        this.age =  obj.age;
    }

    greet() {
        return "Hello, " + this.greeting;
    }
}

let param: GreeterInterface = {
    greeting: 'hello',
    lastname: 'hina',
    name: 'love',
    age:1
}
let greeter = new Greeter(param);


let button = document.createElement('button');
button.textContent = "Say: ";
button.onclick = function() {
    console.log(greeter)
}

document.body.appendChild(button)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Managing Autocomplete Functionality in React with Material-UI, Both with and without a Pre

I am in need of an Autocomplete feature that offers the following functionalities: If the initial value has an id greater than 0, then I want the autocomplete to default to the provided object. If the initial value has an id less than or equal to 0, then ...

Having trouble with a nested Angular 2 component not showing up on the page?

I'm currently developing a mobile app with Angular 2 and Nativescript. In my setup, I have the HomeComponent, which includes a DockComponent. The DockComponent is functioning correctly, but now I want to break down the four buttons in the dock into se ...

Having trouble with the Angular 17 Router functionality when running on a node server

I find myself facing an unusual situation. I am currently developing a basic app that needs to navigate from the landing-page (directory '') to a form component (directory '/form') using Angular 17 and node.js with express.js. I have no ...

Using setState as a parameter in a personalized hook in React/Next.js while incorporating TypeScript

I encountered an issue with the following code snippet: import { useState, useEffect } from "react"; type Props = { setState: (value: string) => void; }; const useSomeCustomHook = ({ setState }: Props) => { useEffect(() => { se ...

Typescript: Potential null object error when defining a method

I recently encountered an error message stating "Object is possibly null" while working on the changePageSize method in book-store.component.html. It seems like I need to initialize the object within the class, but I'm not familiar with how to do that ...

TypeScript generic functions causing incorrect typing issues with nested correlated unions

I am currently working on incorporating a predefined TypeScript configuration that can be dynamically loaded into my application. The configuration is structured as shown below: // Base object types type Config<D> = { fn: ({ option }: { option: D } ...

What is the reason behind the lack of covariance in an interface when using a type of T[keyof T]?

I'm attempting to enable type covariance so that Type<Cat> can be treated as a Type<Animal>, for instance, treating a list of Cats as a list of Animals. However, using the type T[keyof T] in a method within the Type interface seems to hind ...

What could be the reason my mat-form-field is not displaying the label?

I'm currently working on a project using Angular Material to build a web page. I am facing an issue with the mat-form-field component as the label is not displaying, and I can't figure out why. Any assistance would be greatly appreciated. Thank y ...

In TypeScript Next.js 14 APP, object literals are limited to declaring existing properties

I encountered an error in my typescript next.js 14 APP. I need assistance resolving this issue, which states: Object literal may only specify known properties, and 'productPackages' does not exist in type '(Without<ProductCreateInput, Pr ...

How to remove a specific type from a generic type in Typescript without using Exclude<>?

I am looking for a solution to prevent my function from working with Moment objects when storing values in local storage. Currently, the function dynamically stringifies and stores values, but I want to exclude Moment objects from being processed. Here is ...

typescript set x and y values to specific coordinates

Trying to map obstacles using a single object. Originally scattered randomly across the map, now I want to hard code X & Y coordinates with an array of numbers. However, TypeScript is only using the last value of the loop for the X coordinate. How can I a ...

Vuejs fails to properly transmit data

When I change the image in an image field, the new image data appears correctly before sending it to the back-end. However, after sending the data, the values are empty! Code Commented save_changes() { /* eslint-disable */ if (!this.validateForm) ...

TS2339 Error: The property 'Default' is not a valid property for type 'string'

Hello, I am a beginner with Angular 2. I have encountered some issues that I need help with: Error Messages: app/components/playing-cables/-update.ts(82,12): error TS2339: Property 'options' does not exist on type 'jQuery'. app/compone ...

What is the method for running a powershell script within protractor testing?

I am attempting to run a powershell script within my protractor test. Protractor spec.ts it("Executing Powershell Script", async () => { browser.get('http://mywebsite.com') var spawn = require('child_process').spawn; ...

Utilizing Custom Validators in Angular to Enhance Accessibility

I'm struggling to access my service to perform validator checks, but all I'm getting is a console filled with errors. I believe it's just a syntax issue that's tripping me up. Validator: import { DataService } from './services/da ...

Is it necessary for TypeScript classes that are intended for use by other classes to be explicitly exported and imported?

Is it necessary to explicitly export and import all classes intended for use by other classes? After upgrading my project from Angular 8 to Angular 10, I encountered errors that were not present before. These issues may be attributed to poor design or a m ...

A specialized type that guarantees a string union includes a particular string literal

I need to define a Mapped type that specifies a field named status which can be either a string or the string value ready: This example works as expected: export type ValidServiceState = HasReady<{ status: "ready" }>; The following should ...

Tips for implementing md-icon in combination with md-autocomplete in Angular Material Design:

How can I include an md-icon in an md-autocomplete field? <md-autocomplete md-selected-item="ctrl.selectedItem" md-search-text-change="ctrl.searchTextChange(ctrl.searchText)" md-search-text="ctrl.searchText" md-items="it ...

How can a border be applied to a table created with React components?

I have been utilizing the following react component from https://www.npmjs.com/package/react-sticky-table Is there a method to incorporate a border around this component? const Row = require("react-sticky-table").Row; <Row style={{ border: 3, borderco ...

React is struggling to locate the specified module

Once I've set up my react project using npx create-react-app called my-app, I proceed to run npm start only to encounter the error shown in the image below. Running node version: 12.16.1 with npm version: 6.13.4 View the error message her ...