Extending an interface in TypeScript to include an Array

Can I implement a parent interface in Angular 4?

export interface Devices extends Array<Device> {
}

The error 'Class 'DevicesModel' incorrectly implements interface 'Devices'. Property 'includes' is missing in type DevicesModel' occurs when trying to do so.

export class DevicesModel implements Devices {
    constructor() {
    }
}

I suspect that since it's an instance of an array, adding other attributes to the model is not allowed.

I am separating Swagger models from application models by implementing all Swagger generated models. This way, modifications can be made without losing them when regenerated. If this isn't possible, I may need to use composition technique.

EDITs:

More Information:

This is how my Swagger YAML looks like defining rest services.

Devices:
  type: array
  description: list of devices
  items:
    $ref: '#/definitions/Device'
Service:
  type: object
  required:
    - serviceId
    - serviceName
  properties:
    serviceId:
      type: string
    deviceName:
      type: string
    serviceName:
      type: string
    port:
      type: string
    tag:
      type: string

My Swagger generated Rest server model looks like this:

@ApiModel(description = "list of devices")
@Validated
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-02-23T10:57:40.757-05:00")

public class Devices extends ArrayList<Device> implements Serializable {
  private static final long serialVersionUID = 1L;
....
}

When generating a Typescript REST client using Swagger codegen, Devices model is created as:

export interface Devices extends Array<Device> {
}

Changing the YAML so that generated objects don't extend Array but use composition might be the safest bet:

public class Devices implements Serializable 
{
     private static final long serialVersionUID = 1L;
     private List<Device> devices;
     ....
}

In Typescript:

export interface Devices {
     devices: Array<Device>;
}

Since I'm new to Typescript and Angular, applying Java techniques into Typescript is adding complexity. As I continue learning, sticking to a simple solution for now seems best.

Thank you!

Answer №1

If you decide to have your interface Devices extend Array<Device>, it means that any class implementing Devices must also implement all of the methods of an Array, specifically those of an Array<Device>. Essentially, you are attempting to expand upon an Array, which requires defining all the methods available in an Array for your class to be recognized as one, including methods like include among others.

While this explanation sheds light on the situation at hand, it may not align with your intentions. You may find this article insightful as it delves into alternative approaches rather than extending Array.

Remember, TypeScript ultimately compiles down to JavaScript. Since you cannot extend an Array in JavaScript, accomplishing this task in TypeScript may prove to be more complex or less intuitive than anticipated.

The aforementioned article presents various strategies to circumvent this issue, each with their own unique characteristics. These solutions include:

  • Dynamically replacing missing properties at runtime (not optimal due to slower performance and broken inheritance)
  • Avoiding extension of Array altogether but utilizing a parameter that is an Array
  • Implementing workaround techniques to achieve desired functionality by manipulating class constructors

Despite appearing daunting, the final solution might be the most effective here, as it minimizes potential errors during implementation.

To provide further clarity, a snippet from the article's conclusion is shared below:

class MyArray<T> extends Array<T> {
    private constructor(items?: Array<T>) {
        super(...items)
    }
    static create<T>(): MyArray<T> {
        return Object.create(MyArray.prototype);
    }
}

// Demonstrates successful instantiation without using the traditional constructor
const myArray = MyArray.create<string>(); 

In this example, we effectively instantiate the desired object type without relying on its standard constructor, opting instead for Object.create. By introducing a static method to simplify object creation, usability is enhanced.

This response aims to address your query or concern. Given the ambiguity regarding your specific goal, I recommend carefully evaluating whether this solution aligns with your needs.

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

Binding an event to an Angular 2 component directly within its selector code

Looking at my Angular 2 component: import { Component, ElementRef, Renderer } from '@angular/core';; @Component({ selector: 'my-button', templateUrl: 'button.html' }) export class ButtonComponent { private text: string ...

Chrome Driver Protractor Angular 2 encountering issue with unclickable element

My issue is with clicking the second level menu options to expand to the third level. I have tried using browser.driver.manage().window().setSize(1280, 1024) in the before all section. Here is my code snippet: it('Should trigger the expansion of the ...

Retrieve the user information from Auth0 within the NestJS application

I am currently working on implementing Auth0 authorization in NestJS, but I am unsure of how to retrieve the user's data within the callback URL handler. In a normal express function, this issue could be resolved using the following code. The passpor ...

Tracking button clicks on Angular Material using Google Analytics through Google Tag Manager

I'm currently utilizing the Universal Analytics tag within Google Tag Manager to monitor user interactions. I'm looking to establish click listeners in GTM that will trigger when specific buttons on the page are clicked. These buttons are Angular ...

Invoking a Typescript function from the Highcharts load event

Struggling to call the TypeScript function openDialog() from the events.load of Highcharts? Despite using arrow functions, you are running into issues. Take a look at the code snippet below: events: { load: () => { var chart : any = this; ...

"Convert a date string to a date object using the verbose moment date

I utilized the materialize datepicker to select a date in French format. Now I need to convert this formatted date back to a date object for use in my API. Here's how I attempted to revert the date to a standard format: moment("dimanche 30 juillet 20 ...

What is the best way to retrieve a value from an array of objects containing both objects and strings in TypeScript?

Consider this scenario with an array: const testData = [ { properties: { number: 1, name: 'haha' } , second: 'this type'}, ['one', 'two', 'three'], ]; The goal is to access the value of 'second&ap ...

The technique for accessing nested key-value pairs in a JSON object within an Angular application

After receiving the response from the backend, I have retrieved a nested hash map structure where one hash map is nested within another: hmap.put(l,hmaps); //hmap within hmap When returning the response to the frontend, I am using the ResponseEntity meth ...

Issue with Angular 10: Modal window fails to open upon second click

Encountering an issue with a Modal window overlapping the navigation bar and overlay due to a third-party bundle.js adding dynamic classes and divs under the parent-container. The problem arises from a fixed positioning of one of the classes which causes t ...

Discover the steps to sign up for src updates in an Angular 7 iframe

Seeking a method to subscribe to the src (url) change within an IFrame in an Angular 7 Application. Is there a way to capture the src Change event? ...

Angular: Custom Pipes Now Adding Currency Symbol to Model Values

I have encountered an issue involving two currency pipe examples. One example involves using the pipe directly in the view, while the other utilizes the pipe from the TypeScript code side. However, when attempting to submit form data, the value related to ...

Troubleshooting the Issue with spyOn Functionality in Angular 6 HTTP Interceptor

My goal is to test an HttpInterceptor that logs the response of the `http` request. The interceptor only logs for GET requests and utilizes a log service to do so. Below is the code for the interceptor: import { HttpInterceptor, HttpHandler, HttpEvent, H ...

Is it more efficient to have deps.ts per workspace or shared among workspaces?

Currently, I am in the process of setting up my very first monorepo for a Deno-based application. In this monorepo, the workspaces will be referred to as "modules" that the API code can import from, with each module having its own test suite, among other t ...

How can I bypass a unit test suite in Angular?

Is there a method to skip certain unit tests that should not be executed currently, without resorting to using fdescribe on the ones I do want to run? ...

Typescript Code Coverage with karma-jasmine and istanbul: A complete guide

I am attempting to calculate the Code Coverage for my typescript Code in karma framework using Istanbul. In the karma.conf file, typescript files are added and through karma typescript-preprocessor we are able to conduct unit testing and code coverage of t ...

The ASP.NET Core 3.0 Web API method consistently encounters null values

I've encountered an issue with my Angular app where it displays a 500 server error. Here are the methods I'm using: /*Product Service*/ addNewProduct(newProduct: Product): Observable<Product> { console.log(newProduct); return this.http.po ...

Retrieve deeply nested array data using Angular service observable

My endpoint data is structured like this { 'dsco_st_license': { 'ttco_st_license': [ { 'csl_state': 'AK', 'csl_license_name': &ap ...

Is it possible to interchange the positions of two components in a routing system?

driver-details.component.ts @Component({ selector: 'app-driver-details', templateUrl: './driver-details.component.html', styleUrls: ['./driver-details.component.css'] }) export class DriverDetailsComponent implements OnI ...

Ways to extract information from a database using a parameter

I am currently working with angular cli version 8.1.0 and I have a requirement to pass parameters in the URL and retrieve data from a PHP MySQL database. On the PHP side, everything is functioning correctly and the URL looks like this: http://localhost/rep ...

What return type should be used when returning `_.orderBy` from a TypeScript function?

The current packages I have installed are lodash and @types/lodash. In my code, I am using: import _ from 'lodash'; function doSomething(): string[] { const letters = ['c', 'a', 'b']; return _.orderBy(letters ...