Can TypeScript interfaces be used to achieve the same functionality as an abstract class?

I am currently working on developing a function that will return an array type with custom methods, allowing me to utilize it across various sections of the application.

Typically, this is achieved using Abstract Classes where abstract methods are defined and each class extending it must implement these methods in its unique way. However, I am curious if TypeScript interfaces can be used to achieve a similar outcome.

The following code snippet outlines what I aim to accomplish:

1: Retrieving data from an API endpoint, knowing that it will always return an array of objects. Depending on the specific API method called, the objects may have varying attributes.

2: Understanding the structure of the API response, for instance, calling /posts will result in an array with objects containing a 'name' property. In contrast, calling /posts2 requires a 'specialname' property to be returned when invoking Posts[i].myCustomGetter().

3: The goal is to use the 'Posts' interface in different parts of the application, consistently accessing myCustomGetter without being concerned about the implementation details.

import axios from 'axios'

interface Posts {
    [index: number]: Post
}

interface Post {
    // Expected properties from Axios Response Data
    // Additional custom functions based on usage
    myCustomGetter: () => string
}

export async function getPosts(): Promise<Posts> {
    return new Promise<Posts>((resolve, reject) => {
        axios
            .get<Posts>('https://jsonplaceholder.typicode.com/posts')
            .then((response) => {

                // Defining the myCustomGetter function declaration here
                // For example, setting myCustomGetter() => { return thisPost.name }
                // Utilizing API knowledge to determine existing properties

                resolve(response.data)
            })
            .catch((error) => {
                reject(error)
            })
    })
}

Your assistance in clarifying this matter would be greatly appreciated.

Answer №1

I have devised a solution by combining an interface and class.

import axios from 'axios'

interface IPosts {
    items: any[]
    get(index: number): Post
}

interface Post {
    name: string
}

export class Posts implements IPosts {
    items: any[]

    constructor(items: any[]) {
        this.items = items
    }

    get(index: number): Post {
        const item = this.items[index]
        return {
            // This type of post items has a property named title.
            name: item.title,
        }
    }
}

export async function retrievePosts(): Promise<Posts> {
    return new Promise<Posts>((resolve, reject) => {
        axios
            .get('https://jsonplaceholder.typicode.com/posts')
            .then((response) => {
                resolve(new Posts(response.data))
            })
            .catch((error) => {
                reject(error)
            })
    })
}

Now, to access a Post at a specific position (e.g., 0), I use the following approach:

retrievePosts()
    .then((Posts: Posts) => {
        console.log(Posts.get(0))
    })
    .catch((error) => {
        console.log(error)
    })

If I want to ensure that a function expects a class implementing IPost, I utilize generic constraints in TypeScript:

function PerformAction<T extends Posts>(arg: T): void {
    console.log(arg.get(0))
}

retrievePosts()
    .then((Posts: Posts) => {
        PerformAction(Posts)
    })
    .catch((error) => {
        console.log(error)
    })

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

Angular 14 is throwing an error due to an indent issue - the expected indentation is 2 spaces but 4 spaces were found

Currently using "eslint": "^8.23.0" with angular 14. Everything was functioning properly with "eslint": "^8.22.0", but after updating to 8.23.0, I encountered the following error: https://i.sstatic.net/UALvS.png ...

Angular: Issue encountered while attempting to differentiate an '[object Object]'. Arrays and iterables are the only permissible types for this operation

I encountered the following error message while attempting to retrieve updated data: Error trying to diff '[object Object]'. Only arrays and iterables are allowed Snippet of Get Code: allDatas allData(data) { this.allDatas = data } Up ...

Troubleshooting Typescript with Chrome when packaged by Webpack on Visual Studio 2017 using .NET Core 2.2

Many questions have been asked about debugger issues in Visual Studio 2017 with TypeScript and Webpack. Despite the common answer being that it should work by default, my debugger is still not functioning properly. I am new to TypeScript and Webpack, so I ...

Tips for incorporating a conditional background color in a styled component with react and typescript

Is there a way to dynamically change the background color of a styled component based on a condition using React and TypeScript? What I am attempting to achieve: I have a MainComponent that displays ListContent within a DragAndDropComponent. When a user ...

Creating a class in TypeScript involves declaring a method that takes a parameter of type string, which matches the property name of a specific derived class type

I am working on a scenario where I have a base class containing a method that can be called from derived classes. In this method, you provide the name of a property from the derived class which must be of a specific type. The method then performs an operat ...

The JSX element 'HeaderPublic' does not contain any construction or calling signatures

I am currently utilizing nx workspace to build the react ts application. Below is the library component: import { ReactElement } from 'react'; import styles from './header-public.module.scss'; export function HeaderPublic(): ReactElem ...

Concealing the sidebar in React with the help of Ant Design

I want to create a sidebar that can be hidden by clicking an icon in the navigation bar without using classes. Although I may be approaching this incorrectly, I prefer to keep it simple. The error message I encountered is: (property) collapsed: boolean ...

Ensuring accurate properties are sent to popup notifications

As a newcomer to a React & ASP.NET project, I am facing a challenge in displaying upload status notifications. The task may seem simple, but I need help in figuring out how to create popup notifications that indicate which files have been successfully uplo ...

true not redirecting to 404 page when axios request fails

I have implemented Axios to access a basic API. My goal is to direct the user to the default Next.js 404 page in case of a failed request with a 404 error code. I have set the notFound boolean to true if the request status is 404. There are a total of 10 u ...

Can components be SSGed individually rather than entire pages?

I am currently working with Next.js and I am wondering if there is a way to statically generate and display the database values in the header and footer components used across all pages. While getStaticProps can generate pages statically, it doesn't ...

Ensuring type safety in TypeScript arrow function parameters

I have encountered an issue with my code when setting "noImplicitAny" to true. import ...; @Injectable() export class HeroService { private _cachedHeroes: Observable<Hero[]>; private _init: boolean; private _heroesObserver: Observer<Hero[ ...

When the imagepath in an Angular application is not updated, it will revert to null

Below is the code snippet that I am currently working on: <div class="col-sm-4 pl-5"> <img attr.src="{{item?.imagePath}}" required height="200" width="200"> </div> In my TypeScript file (ts), I have the following function: editBlog ...

Utilizing the split function within an ngIf statement in Angular

<div *ngIf="store[obj?.FundCode + obj?.PayWith].status == 'fail'">test</div> The method above is being utilized to combine two strings in order to map an array. It functions correctly, however, when attempting to incorporate the spli ...

Building a Dynamic Checkbox Validation Feature in Angular Using Data retrieved from an API

Currently, I have a function that retrieves and displays a list obtained from an API: displayEventTicketDetails() { this.Service .getEventTicketDetails().subscribe((data: any) => { this.eventTicketDetails = data.map(ticket => ticket. ...

Encountering compilation errors during the vue-cli build process

My Vue 2.2.3 application is experiencing difficulties in the build process due to 4 TypeScript-related errors that are perplexing me. This is the error output displayed on the console: Failed to compile with 4 errors ...

What is the best way to determine the final letter of a column in a Google Sheet, starting from the first letter and using a set of

My current approach involves generating a single letter, but my code breaks if there is a large amount of data and it exceeds column Z. Here is the working code that will produce a, d: const countData = [1, 2, 3, 4].length; const initialLetter = 'A&a ...

My goal is to intentionally trigger an eslint error when importing a file from index.ts

Is there a way to enforce importing components from index.ts within the src/components directory using eslint rules or plugins? // index.ts (src/components/Forms) export { Input } from './Input'; export { CheckBox } from './CheckBox'; ...

The Angular template loads and renders even before the dynamic data is fetched

I'm encountering a frustrating issue where the page loads before the data is retrieved. When I log the names in $(document).ready(), everything appears correct without any errors in the console. However, the displayed html remains empty and only shows ...

Enhancing HTML through Angular 7 with HTTP responses

Sorry to bother you with this question, but I could really use some help. I'm facing an issue with updating the innerHTML or text of a specific HTML div based on data from an observable. When I try to access the element's content using .innerHTM ...

Divide the code into individual components within Angular 2 projects

I currently have 3 Angular 2 projects developed in TypeScript. Each project contains the same models and services. I would like to find a way to integrate these common elements at a global level and connect them with each individual project. Any suggesti ...