0

First of all, to avoid closure of this question, I am aware that this question has a very similar title here:

Property '...' has no initializer and is not definitely assigned in the constructor

But, the biggest problem is that it was asked 5 years ago, and most of the answers are directed to TypeScript Version 2.9.

I am facing the same error message, but in Angular 16 - Which uses TypeScript 4.9.

I tried the answers and solutions in the question above, but they did not work for me, in my Angular Component.

The problem I am having is that I want to declare a variable that will be a array of a specific object type inside my Class component.

This is what I tried so far, using the suggestions from the other answer above, by @Sajeetharan:

// Interface
export interface PhotosApi {
  albumId?: number;
  id?: number;
  title?: string;
  url?: string;
  thumbnailUrl?: string;
}

And this is my component:

import {Component, OnInit} from '@angular/core';

// Importar o cliente para fazer os requests na API
import { HttpClient } from '@angular/common/http';
import { throwError } from 'rxjs';

// Importar a Interface do Slide
import { PhotosApi } from "./interfaces/photos-api";

@Component({
  selector: 'app-row-clients',
  templateUrl: './row-clients.component.html',
  styleUrls: ['./row-clients.component.css']
})

// Exportar a Classe que vai ser o Template da Row Componentes
export class RowClientsComponent implements OnInit {

  limit: number = 10; // <==== Number of API results

  // Sessão de construtor da request da API
  constructor(
    private readonly http: HttpClient, private apiData: PhotosApi
  ) {
    // @Sajeetharan's solution
    this.apiData: PhotosApi = [];
  }

  ngOnInit() {
    this.fetch()
  }

  // Mapear os objetos do tipo PhotosApi para a apiData
  fetch() {
    const api = `https://jsonplaceholder.typicode.com/albums/1/photos?_start=0&_limit=${this.limit}`;
    const http$ = this.http.get<PhotosApi>(api);

    http$.subscribe(
      res => this.apiData = res,
      err => throwError(err)
    )
  }
}

It is not working. It throws a error inside the constructor. Before, I was trying to initialize it like this:

export class RowClientsComponent implements OnInit {
    apiData: PhotosApi;
    // Etc...

Which throws the error in the title, and also mentioned on that other question.

I am basing my component using the following StackBlitz tutorial, which does not work and also causes errors.

The "any[]" does remove the error but as I specified before, it will be a array of object type PhotosApi - Just like in Java that we can create arrays of specific and defined objects (Something like ArrayList).

I appreciate any help

Edit 1: I changed the code to achieve the logic "This is a empty array of PhotosApi objects that will be populated later with PhotosApi objects."

This is the new Export Class, I added comments on what changed:

// Export my class which will be my Angular component
export class RowClientsComponent {
  limit: number = 10; // <==== Number of API results

  // Sessão de construtor da request da API
  constructor(
    private readonly http: HttpClient, private apiData: PhotosApi[]
  ) {
    // @Sajeetharan's solution -- Now there is no more errors in the code IDE.
    this.apiData = []
  }

  ngOnInit() {
    this.fetch()
  }

  // Map objects of type PhotosApi into apiData array.
  fetch() {
    const api = `https://jsonplaceholder.typicode.com/albums/1/photos?_start=0&_limit=${this.limit}`;
    const http$ = this.http.get<PhotosApi>(api);

    // Now, here, on IDE I've been seeing two errors:
    // TS2322: Type 'PhotosApi' is not assignable to type 'PhotosApi[]'.
    // TS2740: Type 'PhotosApi' is missing the following properties from type 'PhotosApi[]': length, pop, push, concat, and 29 more
    http$.subscribe(
      res => this.apiData = res,
      err => throwError(err)
    )
  }
}

And, this is what the compiler shows me:

Errors in Compiler

Edit 2: Tried following the syntax on this answer specifically, alongside what @JaredSmith told me, like this:

Way #1

// Export my class which will be my Angular component
export class RowClientsComponent {
  limit: number = 10; // <==== Number of API results

  // Array of Objects - The equals signs tells: Initialize the Array of Objects when declaring it.
  apiData: PhotosApi[] = Array<PhotosApi>;

Way #2

  // Array of Objects - The equals signs tells: Initialize the Array of Objects when declaring it.
  apiData: PhotosApi[] = PhotosApi[];

And in both methods I got TS2693: 'PhotosApi' only refers to a type, but is being used as a value here.

Raul Chiarella
  • 518
  • 1
  • 8
  • 25
  • 1
    The version of Typescript doesn't matter. You are trying to say that an array is a instance of the PhotoApi interface, which is an object not an array. Make it either `Array` or `PhotoApi[]`. If that doesn't fix the issue you'll need to post more information, what is the *exact* error the compiler is giving you? – Jared Smith Aug 18 '23 at 17:44
  • 1
    "*But, the biggest problem is that it was asked 5 years ago, and most of the answers are directed to TypeScript Version 2.9.*" that's not "the biggest issue" considering absolutely nothing has changed in this regard. Literally all possible solutions are already enumerated in the linked question: initialise the property at declaration, or in the constructor, or use `!` in the declaration *if you ensure initialisation*. The biggest problems in your code are: 1. `this.apiData: PhotosApi = [];` is not valid TS as you shouldn't be using a type annotation 2. you're assigning an array not an object. – VLAZ Aug 18 '23 at 17:52
  • 1
    Does this answer your question? [Property '...' has no initializer and is not definitely assigned in the constructor](https://stackoverflow.com/questions/49699067/property-has-no-initializer-and-is-not-definitely-assigned-in-the-construc) – VLAZ Aug 18 '23 at 17:52
  • As I stated previously, I did what the answers there told it to do but It did not work. @JaredSmith I edited the question adapting to your suggestion, and if I understood it correctly what this is doing is: Create a empty array of PhotosApi objects type... It's on the bold edit 1. – Raul Chiarella Aug 18 '23 at 19:06
  • @VLAZ I don't really get it - `this.apiData: PhotosApi = [];`... Ok. I did'nt understand what you meant. So... The flow that I am not following is: 1. Initialise the property at declaration or in the constructor - But I tried that and it creates the error in the title. I don't want this to be initialized as a array of any[] object type... It is not a array of any[] type - It's a array of PhotoApi type. But, for a initial step this is really useful - You pointed out that my TS syntax is incorrect. I will keep trying. – Raul Chiarella Aug 18 '23 at 19:15

2 Answers2

1

You need to properly declare your arrays of PhotosApi objects. You seems to be confusing the parts where you declare your types and the parts where you initialize a value.

You have tried the following

apiData: PhotosApi[] = PhotosApi[];
//or
apiData: PhotosApi[] = Array<PhotosApi>;

but both of these are invalid syntax. You are repeating the type again where you initialize the value, don't do that. Instead it should be:

apiData: PhotosApi[] = [];
//or
apiData: Array<PhotosApi> = [];

generally speaking you only use a type between the : and the = symbols. Of course there are other ways to declare or force types, but you don't need to do that here.


You also have

this.http.get<PhotosApi>(api)

which says you are expecting a single PhotosApi to be returned, but you probably want an array here also. This should probably be like this instead:

this.http.get<PhotosApi[]>(api)
Chris Barr
  • 29,851
  • 23
  • 95
  • 135
  • 1
    Thank you very much - I was not understanding the logic behind this, and now I got it. It worked like a charm... I did not know how to declare and initialize my array of `PhotosApi` objects. Things are much clearer now. God bless you! – Raul Chiarella Aug 18 '23 at 20:15
0

You need to do it like this:

export class RowClientsComponent implements OnInit {
  limit = 10; // no need to specify the type here, it's inferred automatically from the assigned value
  apiDate: Array<PhotosApi> = []; // here we specify the type of the contents in the array - and initialize it with an empty array
  constructor(private readonly http: HttpClient) {}
  // other codes
}
msrumon
  • 1,250
  • 1
  • 10
  • 27