0

I am having this problem for the first time, I think it is because of the promise here and waiting. Anyone know how to fix this? I put the part of the code where the error occurs, the whole class and the error at the bottom.

Part of code with error:

this.languages = await this.languageService.getAll().toPromise()

    this.languages.forEach(async (language) => {
      this.languageOption = new DropdownOption

      this.languageOption.set (
        language.getName(),
        language.getId()
      )

Language class:

export class Language {
    private id: number;
    private name: string;
    private code: string;
    private charset: string;
    private isDefault: boolean;
    private isActive: boolean;
    private systemId: number;

    public constructor() {
        this.id = null;
        this.name = '';
        this.code = '';
        this.charset = '';
        this.isDefault = false;
        this.isActive = false;
        this.systemId = null;
    }

    public set(
        _id: number,
        _name: string,
        _code: string,
        _charset: string,
        _isDefault: boolean,
        _isActive: boolean,
        _systemId: number
    ) {
        this.id = _id;
        this.name = _name;
        this.code = _code;
        this.charset = _charset;
        this.isDefault = _isDefault;
        this.isActive = _isActive;
        this.systemId = _systemId;
    }

    public getId(): number {
        return this.id;
    }

    public getName(): string {
        return this.name;
    }

    public getCode(): string {
        return this.code;
    }

    public getCharset(): string {
        return this.charset;
    }

    public getIsDefault(): boolean {
        return this.isDefault;
    }

    public getIsActive(): boolean {
        return this.isActive;
    }

    public getSystemId(): number {
        return this.systemId;
    }

    public setId(_id: number): void {
        this.id = _id;
    }

    public setName(_name: string): void {
        this.name = _name;
    }

    public setCode(_code: string): void {
        this.code = _code;
    }

    public setCharset(_charset: string): void {
        this.charset = _charset;
    }

    public setIsDefault(_isDefault: boolean): void {
        this.isDefault = _isDefault;
    }

    public setIsActive(_isActive: boolean): void {
        this.isActive = _isActive;
    }

    public setSystemId(_systemId: number): void {
        this.systemId = _systemId
    }
}

Error:

Uncaught (in promise): TypeError: language.getName is not a function TypeError: language.getName is not a function

8
  • 3
    so what does console.log(language) print? Commented Apr 1, 2021 at 11:59
  • one of elements: {charset: 0 code: "en" id: 2 isActive: true isDefault: true name: "english" systemId: 1033} Commented Apr 1, 2021 at 12:17
  • 2
    I guess languageService.getAll() returns "plain" objects and not the instances of Language class Commented Apr 1, 2021 at 12:21
  • this.languages = this.languages.map(lang => new Language(lang)) Commented Apr 1, 2021 at 12:22
  • @AlekseyL. then how to solve it? Commented Apr 1, 2021 at 12:34

2 Answers 2

0

In the forEach try defining the type of each array Element.

Also, try adding an if condition, just to be sure so that you wont get errors.

Something like this:

this.languages.forEach(async (language: Language) => {
  if (language) {
    // Write your code here. 
  }
})

If you get an error in the above implementation, it means that the languages is not returning an array of Languages . So you have to map it and then use the forEach

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, i got error once and nothing happens
Can you put your code into a stackblitz and paste it here? It is hard to solve an issue without looking at the code. What does console.log('Languages ==>', this.languages) print?
it return list of languages like [{id: 1 ....}, {...},], all 31 elements
Ok, theoretically, it should not cause an issue. But can you reproduce this in stackblitz please? Because its hard to tell without actually looking at the code.
0

The problem is that your service does not return objects of the Language class, but instead returns objects that have the same structure as the class.

(The class looks created by a Java developer, so the rest of my suggestions will be under that assumption)

In Java, objects are (usually) created by invoking a constructor. On the other hand objects in JavaScript are usually created by the object literal syntax {...}. This has the consequence that, while in Java constructors are a much-needed tool, in JavaScript, constructors (and even classes) are mostly useless, especially in data transfer scenarios.

So, in order to have idiomatic (i.e. good) TypeScript code, I would recommend removing the class altogether, and switching to an interface:

export interface Language {
    id: number;
    name: string;
    code: string;
    charset: string;
    isDefault: boolean;
    isActive: boolean;
    systemId: number;
}

Now, unlike Java interfaces, which have to be formally declared to be used, TypeScript interfaces are structural. This means that any object that has these fields is, for all intents and purposes, a Language. Yes, this means that we can have an object that is constructed as a literal and is considered to implement an interface. (That's why usually interfaces in TypeScript do not have the I prefix)

Also, don't worry about unencapsulated access to the fields. Some might think it's crazy, but we're fine with it in JS land :)

Now, if we assume that the languageService.getAll().toPromise() returns an array of Language objects (again, the interface, not the class), we can write the needed code like this:

this.languages = await this.languageService.getAll().toPromise()

//using for..of, as I hate forEach
for (const language of this.languages) {
  // ....
  this.languageOption.set(
    language.name,
    language.id
  );
  // ...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.