Checking types in Angular with interfaces

How can strict type checking be implemented in Angular for the returned response?

1. Utilize a data.json file for temporary API purposes

[
  {
    "name": "Someone 1",
    "comment": "comment 1",
    "line": "line 1"
  },
  {
    "name": "Someone 2",
    "comment": "comment 2",
    "line": "line 2"
  },
  {
    "name": 3,
    "comment": "comment 3",
    "line": "line 3"
  }
]
  1. Define a model interface
export interface Model {
  name: number;
  comment: string;
  line: string;
}

3. Service class app.service.ts

export class AppService {
  constructor(private _http: HttpClient) {}

  private api = "../api/data.json";

  loadData(): Observable<Model[]> {
    return this._http.get<Model[]>(this.api);
    //.pipe(tap((data) => console.log("All:" + JSON.stringify(data))));
  }

  loadSingle(): Observable<Model> {
    return this.loadData().pipe(map((data: Model[]) => data[2]));
  }
}

4. Component class app.component.ts

export class AppComponent implements OnInit {

  myvarArray: Model[];

  myvarSingleton: Model;

  constructor(private _appService: AppService) {}

  ngOnInit() {
    this._appService.loadData().subscribe((data) => {
      this.myvarArray = data;
    });

    this._appService.loadSingle().subscribe((data) => {
      this.myvarSingleton = data;
      console.log(data.name + ":" + data.comment);
    });
  }
}

5. app.component.html

<h1>Printing obj data</h1>
<ul *ngFor="let data of myvarArray">
  <li>{{ data.name }} -- {{ data.line }}</li>
</ul>

<h1>Printing Single data</h1>
<span>{{ myvarSingleton.name }}</span>

Is there a way to implicitly implement type checking so that the values in the data.json match the types declared in the interface? I am concerned that even if "name" is specified as a number, it does not throw an error during compilation when the data is returned to app.component. Is there a way to check this without using explicit validation functions?

[Edit] Additionally, why am I receiving an error stating "undefined property on myvarSingleton.name" even though the property is defined in the interface (but the data displays correctly on the page)? And why does it occur three times?

The console shows an error mentioning that "name" is undefined

Answer №1

When working with TypeScript, it is important to note that you cannot directly validate JSON.parse using TypeScript. Instead, you can inform TypeScript about the expected structure of your JSON data. One workaround is to create a validation function like the following example:

function isValidData(arg: any): arg is Data {
  return arg 
  && (arg.name && typeof (arg.name) == 'string')
  && (arg && arg.description && typeof (arg.description) == 'string');
}

It is worth mentioning that the type checking in this function is static. In some cases, casting the JSON data to a class instead of using an interface may offer more flexibility and advantages.

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

Enhancing the functionality of a bootstrap button with the addition of an

My goal is to have a button that opens a URL in a new tab. I've managed to achieve this using window.location.href, but it doesn't open the URL in a new tab. The code I'm working with is written in jQuery and Javascript, and it's part ...

Force jQuery to refresh the data entered in the input field

I have a range slider that updates an input field with data. My goal is to multiply this data by 50 and display the result below it, but unfortunately, the script only seems to work when I manually enter data into the field. For instance, if you input 5 i ...

How should the 'render' function be called once all asynchronous operations in the controller have been completed?

Here we are working with an application built on the CompoundJS framework that includes a specific controller: load('application'); action('index', function () { someMethodWithAsyncCallback({}, function () { /* async prepa ...

The height of the div is set to zero within the $(document).ready() function

From what I understand, when we write JQuery code inside $(document).ready(), the code will only be executed after the DOM has finished rendering. I encountered an issue where I was trying to calculate the height of a div inside $(document).ready() but it ...

Why is ReactCSSTransitionGroup creating numerous components when I am anticipating just one?

While experimenting with ReactCSSTransitionGroup for animations, I encountered a peculiar situation that doesn't quite add up in my understanding. In the scenario below, every time I click on <div className="HeartControl">, it updates the heigh ...

Zoom out the slider when scrolling

Take a look at this link and as you scroll down the page, notice how the image transitions to iPhone. Can anyone provide insight on how this effect is achieved? ...

What is the best way to employ the *ngIf directive in order to alter an image?

I'm in the process of developing an application using the following technologies. How can I implement the use of *ngIf directive to switch between two images? Here's a more detailed explanation: I have two images, one representing the male symbol ...

Several asynchronous calls are made, each returning a boolean value without waiting for them to

One challenge I am encountering is that the searchbar displays "No results found" before showing actual results. This issue is not related to the frontend; rather, it occurs due to the asynchronous nature of the calls. Calls without results complete faster ...

Lazy loading images without the need to manually adjust the image structure

After experimenting with various LazyLoad options, I found that most of them required modifications to the src tag or the addition of a new tag. Is there a way to LazyLoad content without having to change the tag structure? I am extracting content fro ...

Attention! Circular dependency has been detected during compilation with warnings

Every time I attempt to build my project, an error is thrown- WARNING in Circular dependency detected: src\app\own-filter\own.filter.module.ts -> src\app\own-filter\own.filter.component.ts -> src\app\own-f ...

The elements within the NativeScript components are failing to show the data received from the Django API

My Django API is set up to provide a list of movies titles with their corresponding IDs. I've implemented a movie service in TypeScript that retrieves the list of movie titles and IDs using the GET operation. In my NativeScript project, I have two f ...

Unravel the base64 encoded message from JavaScript and process it in Python

I'm currently facing an issue in Python while trying to decode a string sent by jQuery. Although I am not encountering any errors, I receive an encoding error when attempting to open the file. My objective is to decode the string in order to save it ...

*ngFor fails to update existing table rows and instead just appends new rows

In my project using Sonic 3, I am utilizing the SQLite plugin to insert data into a SQLite database. Subsequently, I retrieve this data and display it in my template. This is the TypeScript file: saveData() { this.sqlite.create({ name: 'i ...

Best practices for Angular 2: determining whether to include a service in a component's provider or in a module

I'm finding it hard to determine whether a service should be placed in the component's provider within @Component() or in a NgModule(). For instance, if I have a service that fetches HTTP links for my FooterComponent, should it be included in th ...

ASP.NET sending an AJAX request

Hi, I am new to the world of ajax requests and asp.net. I am facing an issue while sending an ajax request to an aspx page. Even though the server side debugging seems fine, I am encountering an error message in the response. I have already tried changing ...

Angular: Utilizing the extend method in the child controller's scope

I am facing a challenge regarding the extension of methods in an angular child controller which is causing me some frustration. My main objective is to inherit all the public /$scope/ variables and methods from the parent controller into the child controll ...

sending a collection of image data arrays wrapped in FormField objects from Angular to Express

I am facing a challenge while trying to upload two FormField objects along with form data to express. I am having trouble using the multer library in express to extract this data from the request. While I can access the form data, the FormField objects re ...

RxJs operators prevent the need for multiple subscriptions through the use of looping mechanisms

Currently working on developing a navigation component for an Angular application. The code snippet below shows my current progress. I am looking to avoid the common issue of having multiple subscriptions within each other, known as the multiple subscripti ...

Is the Property Decorator failing to substitute the definition?

My code is similar to the following scenario, where I am attempting to replace a property based on a decorator export function DecorateMe() { return function(component: any, propertyKey: string) { Object.defineProperty(component, propertyKey, ...

What is the best way to retrieve the index of the chosen option from a select element in Angular when

My Angular application includes a simple <select> element using Material design: <mat-form-field> <mat-label>Type</mat-label> <mat-select placeholder="Type" formControlName="type" name="type" id="name"> <mat-option ...