Can you explain the distinction between 'extends' and 'implements' in TypeScript programming?

Curious to understand the similarities and differences between a Man and a Child.

class Individual {
  name: string;
  age: number;
}
class Child extends Individual {}
class Man implements Individual {}

Answer №1

Explanation in Brief

  • extends signifies:

The new class acts as a derivative. It inherits the attributes and methods of its parent while being able to override or introduce new ones, but it inherently includes the parent's features.

  • implements denotes:

The new class assumes a similar "shape" to another, although it is not a direct descendant. This allows it to substitute for the equivalent of the specified type, even if it has a different lineage from the original type.

Further Explanation

In the world of OOP (such as C# or Java), we utilize

extends for benefiting from inheritance.

... In object-oriented languages with classes, inheritance is a process where one entity acquires all the attributes and behaviors of the parental entity. Inheritance allows programmers to: construct classes based on existing classes ...

implements is more aligned with polymorphism.

... polymorphism refers to presenting a single interface that can apply to entities of diverse kinds...

Therefore, our class Man could have a distinct inheritance chain:

class Man extends Human ...

but by specifying that Man can masquerade as the Person category:

class Man extends Human 
          implements Person ...

...we permit using it in any scenario requiring a Person. The criteria are simply fulfilling Person's "interface" (i.e., implementing all its public elements).

Implementing another class? That's fascinating!

Javascript showcases an appealing aspect (among many) like built-in support for duck typing.

"If it walks like a duck and it quacks like a duck, then it must be a duck."

Hence, in Javascript, if two distinct objects possess a common method (e.g., render()), they can be utilized interchangeably in functions expecting it:

function(engine){
  engine.render() // any type with render() can fit
}

To maintain this feature in Typescript while enhancing type safety, we incorporate similar concepts with added typed assistance. This plays a pivotal role where applicable.

In OOP dialects like C#, achieving this would be unattainable.

Dive into Documentation for Clarity:

Interfaces Extending Classes

When an interface type extends a class type, it inherits the properties of the class without inheriting their implementations. Essentially, it mimics declaring all members of the class sans providing an actual implementation. Interfaces even inherit private and protected members from a base class. Consequently, creating an interface that extends a class holding private or protected elements restricts its implementation solely to said class or its descendants.

This approach becomes beneficial within extensive inheritance hierarchies when enforcing compatibility exclusively with subclasses embodying specific qualities. Such subclasses need not share any intrinsic relation beyond their ancestral connection. For instance:

class Control {
    private state: any;
}

interface SelectableControl extends Control {
    select(): void;
}

class Button extends Control implements SelectableControl {
    select() { }
}

class TextBox extends Control {
    select() { }
}

// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
    private state: any;
    select() { }
}

class Location {

}

Hence, while

  • extends ensures complete inheritance from the parent
  • implements almost emulates implementing an interface in this context. A child entity can imitate its parent... though devoid of automatic implementation transfer.

Answer №2

When dealing with classes and interfaces in TypeScript (as well as other object-oriented languages), it's important to understand their distinct roles.

An interface serves as a blueprint, outlining what methods and properties a type must have without providing any actual implementation. It essentially defines a "contract" that implementing instances must adhere to.

For instance:

interface Point {
    x: number;
    y: number;
    distance(other: Point): number;
}

In this example, any object implementing the Point interface must include two number-type members (x and y) and a method named distance, which takes another Point instance as a parameter and returns a number.

The real meat of the functionality lies in classes, which are responsible for implementing the details specified by interfaces:

class PointImplementation implements Point {
    public x: number;
    public y: number;
    
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
    
    public distance(other: Point): number {
        return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));
    }
}

As illustrated in the code snippet above, classes provide the actual implementation based on the requirements laid out by interfaces.

It's worth noting that when extending or implementing classes/interfaces, there are subtle distinctions to keep in mind:

class Person {
    name: string;
    age: number;
}

class Child extends Person {}

class Man implements Person {}

In the case of trying to implement the Person interface with the Man class, you may encounter errors if the necessary properties are not defined, highlighting the fact that interfaces do not contain implementations.

To rectify such errors, make sure to explicitly define all required properties within the implementing class:

class NoErrorMan implements Person {
    name: string;
    age: number;
}

Ultimately, the key takeaway is that when working with classes and interfaces, it's essential to grasp the distinction between extending a class (inheriting its properties and methods) and implementing an interface (adhering to a set of rules without inheriting any concrete implementations).

Answer №3

Comparison between Extends and Implements

  • extends: When a child class inherits all properties and methods from the parent class it extends.
  • implements: The class using the implements keyword must implement all properties and methods declared in the interface it implements.

Simplified explanation:

  • extends: Automatically acquires methods/properties from the parent class, eliminating the need for manual implementation.
  • implements: Acts as a contractual obligation for the class to adhere to, ensuring implementation of specified methods/properties.

Example Scenario:

class Person {
  name: string;
  age: number;

  walk(): void {
    console.log('Walking (person Class)')
  }

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
class Child extends Person { }

// Man is required to implement all properties
// and methods of the Person class
class Man implements Person {
  name: string;
  age: number

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  walk(): void {
    console.log('Walking (man class)')
  }

}
    
(new Child('Mike', 12)).walk();
// Output: Walking(person Class)

(new Man('Tom', 12)).walk();
// Output: Walking(man class)

In the given example, we see that the Child class inherits everything from Person, while the Man class must implement all aspects of Person itself.

If something was removed from the Man class, like the walk method, a compile time error would occur:

'Man' does not correctly implement 'Person'. Should you perhaps extend 'Person' to inherit its members as a subclass? Property 'walk' is missing in type 'Man' but is required in type 'Person'.(2720)

Answer №4

What an insightful response from @nitzan-tomer! I found it extremely helpful and decided to expand on his demonstration a bit by incorporating:

IPoint interface;
Point implements IPoint;
Point3D extends Point;

I then explored how these elements behave within functions that expect an IPoint type.

From this experience, I've adopted a rule of thumb: when working with classes and methods that require generic types, utilize interfaces as the expected types. Additionally, ensure that the parent or base-class utilizes that interface so that all subclasses implementing the interface can be used effectively in those scenarios.

You can access the expanded demo here.

Answer №5

In simple terms:

  • extends allows us to inherit all the properties and methods from the parent class.
  • implements requires us to provide implementations for all the properties and methods specified in the interface.

Answer №6

  1. Interface extending another interface with a specific shape
  2. Interface expanding a class with a particular structure
  3. To implement a class that implements an interface, all fields specified by the interface must also be implemented
  4. Implementing a class that has a defined structure
  5. Extending a class that includes all fields from another class

extends focuses on inheritance while implements concentrates on restrictions for interfaces or classes.

Answer №7

Utilizing interfaces in programming serves to decrease the connection between classes by establishing a set of rules or common communication system that dictates how various classes can engage with each other. This approach fosters a more flexible and easily maintainable codebase, as it encourages loose connections and facilitates future expansions (Adopting an interface-driven design). Through the implementation of interfaces rather than inheritance, the interdependencies among classes are minimized, resulting in decreased code entanglement. This separation improves the ability to reuse code, conduct thorough testing, and enhance the overall adaptability of the system.

Answer №8

  • "extends": The keyword is utilized when a class or interface "extends" another class or
    interface> of the same type within its hierarchy.</li>
    <li>"<code>implements
    " : This keyword is used specifically when a class implements an interface.

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

TypeORM is failing to create a table upon initialization

Recently, I delved into the realm of typescript and decided to explore TypeORM for backend development. My current project involves building a CRUD API using typeORM and postgreSQL. After configuring everything initially, I ran the application only to rea ...

Typescript is unable to locate the .d.ts files

Working on a personal project and came across a library called merge-graphql-schemas. Since the module lacks its own typings, I created a file at src/types/merge-graphql-schemas.d.ts In merge-graphql-schemas.d.ts, I added: declare module "merge-graphql-s ...

Dynamic row generation with dropdown menu and data binding

Currently, I am working with a table that dynamically creates rows containing details of uploaded files. Each row includes a dropdown menu for selecting the file type. The issue I am encountering is with the dynamically generated dropdown menus. If I sele ...

Angular 6 Checkbox Selector - Filtering Made Easy

How can I filter a list of JSON objects (Products) by the 'category' variable using checkboxes? An example product object is shown below: { 'bikeId': 6, 'bikeName': 'Kids blue bike', 'bikeCode': ...

Create an array containing elements based on specified type values

How can I create an array that is initialized with values depending on a specific type? type Animals = 'monkey' | 'elephant' | 'lion'; const animalsArray: Array<Animals> = []; // ['monkey', 'elephant&apos ...

Error Encountered: 403 Forbidden Error when Loading PDF in Quill Project using Uploadthing URL

This project is a combination of Next.js with TypeScript, tRPC, MySQL using Prisma, and Pinecone for vector DB. Uploadthing is integrated for PDF uploads. Despite successful upload, there is an issue when trying to open the PDF on the website, resulting in ...

Dealing with Exceptions in NestJS and TypeORM: Troubleshooting "Get Status is not a function"

Currently, I am working on an application utilizing NestJS and TypeORM. My main objective is to handle TypeORM errors by using exception filters. However, I have run into a roadblock as I am facing this particular error: (node:345) UnhandledPromiseReject ...

Why is Sentry choosing to overlook certain errors in my React application?

While using Sentry to catch errors in my React app, I discovered that it ignores errors with 502 and 504 HTTP codes as well as some React errors. I am unsure why this is happening and would like to modify this behavior. Below is the initialization functio ...

What is the best way to set up a reactive form in Angular using the ngOnInit lifecycle

I have been facing an issue while trying to set up my reactive form with an observable that I subscribed to. Within the form class template, I used the ngOnInit lifecycle hook to fetch the desired object, which is the product. The first code snippet repre ...

Is there a way to modify the antd TimePicker to display hours from 00 to 99 instead of the usual 00 to 23 range?

import React, { useState } from "react"; import "./index.css"; import { TimePicker } from "antd"; import type { Dayjs } from "dayjs"; const format = "HH:mm"; const Clock: React.FC = () =& ...

add headers using a straightforward syntax

I'm attempting to append multiple header values. This is what I'm currently doing: options.headers.append('Content-Type', 'application/json'); options.headers.append('X-Requested-By', 'api-client'); ... ...

Using Angular 2 to submit ngModel data within an ngFor loop

When submitting the form, an error occurs when trying to repopulate the data back to the form: ERROR TypeError: Cannot read property 'id' of undefined This is in reference to the code snippet: <select [(ngModel)]="insurer.group.id" name="grou ...

Guide to leveraging tanstack table v8 for sorting data within a specific date range

Received data from API: const abc = [ { date: '2023-12-8', value: 'mop' },{ date: '2023-10-8', value: 'qrs' } ] How can we create a date range using two input fields when the dates are in string forma ...

Why does React consider my array to be empty when it's being accessed within a function that is triggered by a websocket message?

While working with React, I encountered a peculiar issue. I have an array variable named messages defined using the useState hook. Additionally, there is a component on the page that listens for events on a websocket but doesn't contain any DOM elemen ...

Anonymous function bundle where the imported namespace is undefined

Here is the code snippet I am working with: import * as Phaser from 'phaser'; new Phaser.Game({ width:300, height:300, scale: { mode: Phaser.Scale.FIT, }, type: Phaser.AUTO, scene: { create() {} }, }); Upon compi ...

Encountering an error with type mismatch for style transform properties while using react-native-reanimated

Currently working with the following versions: "react-native": "0.59.10" "react-native-reanimated": "^1.3.0" using TypeScript Encountering a type error related to transform properties. const Example = () => { const { translationX, gestureHandler } = ...

Sacrificing type safety versus retaining type safety

I'm curious to know what sets apart these two approaches when declaring the status property. I understand that the second version maintains type safety, but how exactly does it achieve this? export type OwnProps = { id: number; name: string; sta ...

The `$refs` variable in Vue can be used to reference a specific Vue component within a class-st

Would it be possible to access this.$refs.label? I am using the package vue-property-decorator. Below is the content of the component: <template> <div> <label ref="label">asd</label> </div> </template> <scr ...

Angular fails to combine values within routerLink

The issue is straightforward - I have a component that retrieves the last searched items saved in sessionStorage as an array of ListItem objects: export class SearchlistComponent { results = JSON.parse(<string>sessionStorage.getItem("lastSear ...

Unable to utilize AgmMarkerSpiderModule

I followed the instructions to add the AgmMarkerSpiderModule from the official package documentation. However, when I compile, I encountered the following error message: /directives/marker-spider.ts:14:24 - error TS2307: Cannot find module '@agm/core/ ...