Can you explain the distinction between inheritance and union types in regards to portraying polymorphism?

Exploring union types in Typescript, I have discovered a new way to showcase polymorphism without relying on inheritance. In my previous Java background, I would typically approach it like this:

interface Emotion {
  display(): string;
}

class Joy implements Emotion {
  display() {
    return '😄';
  }
}

class Sorrow implements Emotion {
  display() {
    return '😢';
  }
}

However, I have now realized that the same concept can be achieved using unions:

class Joy {
  display() {
    return '😄';
  }
}

class Sorrow {
  display() {
    return '😢';
  }
}

type Emotion = Joy | Sorrow;

What are the potential theoretical or practical distinctions between these two approaches?

One notable difference is that the first method allows any value of type Emotion to be any class that implements the Emotion interface. On the other hand, the second approach restricts Emotion to be only Joy or Sorrow instances.

Are there any other aspects that I might have overlooked?

Answer â„–1

When looking at those specific properties, there isn't much variation. The behavior of Smiley will mimic the type { print: () => string }. Both versions will not restrict it so that only Happy and Sad can match the type; someone could create a new object with a print function that returns a string, and it would still match Smiley

However, once additional properties are introduced, they will behave differently. If a common property is added to both classes, then example 2 will automatically include that property in Smiley. In contrast, in example 1, Smiley will only receive an additional property if it is added directly to Smiley, not if it is added to Happy/Sad.

Another important scenario is when they possess properties that are distinct. This is where unions become extremely valuable. Any shared properties between the types can be accessed without TypeScript raising any objections, but properties that are unique cannot be accessed unless appropriate checks are performed to narrow down the type.

class Happy {
  print() {
    return ':-)';
  }
  greet() {
    return 'hi';
  }
}

class Sad {
  print() {
    return ':-(';
  }
  exterminate() {
    return 'bye';
  }
}

type Smiley = Happy | Sad;

const example: Smiley = /* some object; maybe it's a Happy, maybe it's a Sad, maybe something else matching Smiley*/

example.print(); // Allowed by TypeScript
if ('greet' in example) {
  example.greet(); // Allowed, as we have narrowed it down to a Happy
}
example.exterminate(); // Not allowed, as there is no confirmation that it's a Sad

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

Leveraging LESS in an Angular2 component

Currently, I am attempting to integrate LESS with angular2. To do so, I have imported the less.js file in my index.html and I am using the following command within the component: less.modifyVars({ '@currentTheme-bar': '@quot ...

Move to the top of the page when the next action is activated

I am working with an Angular 8 application. Within the application, I have implemented navigation buttons for next and previous actions. My goal is to ensure that when a user clicks on the "next" button, the subsequent page starts at the top of the page ...

There was a mistake: _v.context.$implicit.toggle cannot be used as a function

Exploring a basic recursive Treeview feature in angular4 with the code provided below. However, encountering an error when trying to expand the child view using toggle(). Encountering this exception error: ERROR TypeError: _v.context.$implicit.toggle i ...

A guide on efficiently storing and retrieving a webpage containing two angular2 components using local storage

I've been attempting to store and retrieve a page containing two angular2 components from local storage using the following code, but the component CSS is not being applied. Here is the code I'm using to save: localStorage.setItem('pageCon ...

Encountered an issue while attempting to assign a value to a property that is declared as [key in keyof T]

I am currently working on implementing a function that selects specific properties of an object. Here is the current function: const project = function<T>(object: T, projection: Projection<T>): Partial<T> { throw new Error("not imple ...

Child component experiencing issues with Materialize Pagination and Sorting functionalities not functioning

New to materialize pagination and currently working on the hierarchy below: app modules > list > list.component app.component Implemented a sample code example in app.component which worked perfectly. However, encountered issues when trying to imp ...

What is the process for specifying a method on a third-party class in TypeScript?

I'm facing a challenge while trying to extend a third-party class in TypeScript. The issue is that I am unable to access any existing methods of the class within my new method. One possible solution could be to redeclare the existing methods in a sep ...

The data type 'UserContextType' does not qualify as an array type

I am facing an issue related to context in React. I am attempting to set an object as the state. While it works fine locally, when I try to build the project, I encounter an error message stating: Type 'UserContextType' is not an array type. I a ...

What is the best way to guarantee that an object contains certain fields using Partial<>?

I am dealing with a function that accepts a parameter as shown below: const handleAccount = ( account: Partial<IAccountDocument>, ... ) => { ... } It is crucial that the interface for IAccountDocument cannot be modified to avoid requiring cer ...

Challenge with React CloneElement regarding typing

Utilizing React Children and React Clone element, I aim to trigger methods in both the wrapper and Select components upon onClick event in the Option component. Although everything is functioning correctly, I am encountering a type error when calling the O ...

"Overcoming obstacles in managing the global state of a TypeScript preact app with React/Next signals

Hello, I recently attempted to implement a global app state in Preact following the instructions provided in this documentation. However, I kept encountering errors as this is my first time using useContext and I suspect that my configuration might be inco ...

How can I create an input field in MUI that restricts input to letters, numbers, and dashes

Is there a way to configure an MUI input field so that it only accepts letters, numbers, and dashes while excluding spaces and symbols such as (*&^%$#@!,.<>{}[])? Specifically, I want to allow characters that wouldn't disrupt a URL, like . Tha ...

Leverage the Node Short ID library in conjunction with Angular 6 using TypeScript

I attempted to utilize the node module within an Angular 6 typescript environment. Step one: npm i shortid Within my TypeScript class: import { shortid } from 'shortid'; let Uid = shortid.generate(); However, I encountered an error stating ...

Loading a Dynamic URL within a Component's template in Angular 2.0.0-rc.1

Is there a method for dynamically loading URLs in the templateUrl property? Similar to the code snippet below: @Component({ moduleId: module.id, selector: 'my-app', templateUrl: DynamicUrl, // Load DynamicUrl here styleUrls: [&ap ...

Delay the execution until all promises inside the for loop are resolved in Angular 7 using Typescript

I am currently working on a project using Angular 7. I have a function that contains a promise which saves the result in an array as shown below: appendImage(item){ this.imageCompress.compressFile(item, 50, 50).then( result => { this.compressedI ...

Show every item from a collection on individual lines within an Angular2 module

I am working with an Angular2 component that is responsible for displaying a list of speakers stored in some data. Currently, when I add the code below to my xyz.component.html, it shows the list as comma-separated strings. However, I would like each speak ...

Visual Studio Code unable to locate source maps for typescript debugging

Looking for some help debugging a basic Hello World TypeScript file. Whenever I try to set a breakpoint, it seems like VS Code is having trouble locating the source map, even though it's saved in the same directory. I'm using Chrome as my browser ...

Convert individual packages within the node_modules directory to ES5 syntax

I am currently working on an Angular 12 project that needs to be compatible with Internet Explorer. Some of the dependencies in my node_modules folder are non es5. As far as I know, tsc does not affect node_modules and starts evaluating from the main opti ...

Invoke a general function with corresponding generic parameters

I am currently working on a function that takes another function and its arguments as parameters, then runs the function with the provided arguments and returns the result while maintaining the data types. If the function being provided has a fixed return ...

Error message received when making an API call in React Native for Android and saving the response to a local database: 'Error: Network

Despite using axios and promises to make a call to a local database API, I am facing difficulties reaching the endpoint as I constantly receive a 'Error: Network Error' feedback in the console without any further explanation on the root cause of ...