Home > Software engineering >  Angular template - rendering a variable that can be many different types
Angular template - rendering a variable that can be many different types

Time:07-02

Scenario:

I have an endpoint that returns the questionnaire (AnsweredQuestion[]) of the following interface

interface AnsweredQuestion {
questionText: string,
questionType: string,
answer: number | SingleAnswer | MultiAnswer
}

interface SingleAnswer {
answerId: number,
answerText: string
}

interface MultiAnswer {
answers: SingleAnswer[]
}

questionType is related to answer's interface and there's more different types than those 3. Even more advanced ones.

Unfortunately, I can not change it. Also, I have strict TSLint rules, so I can't use any type.

I need to render it in the component's template. My first try was to just loop over those objects and rendering it depending on questionType like so

<div *ngFor="let answeredQuestion of answeredQuestions">
    <ng-container *ngIf="answeredQuestion.questionType === 'int'">
        {{ answeredQuestion.answer }}
    </ng-container>
    <ng-container *ngIf="answeredQuestion.questionType === 'single'">
        {{ answeredQuestion.answer.answerText }}
    </ng-container>
    ... and so on


</div>

But the linter throws an error Property 'answerText' does not exist on type 'number | SingleAnswer | MultiAnswer'. (I'm sure it does, because my if *ngIf="answeredQuestion.questionType === 'single'" makes sure that I'll get the correct type, but the linter doesn't know that.)

Question: What's the cleanest solution to solve the problem?

I have other (working) ideas, but I don't like them

  1. Parsing all types to some new unified interface. But that interface would be quite advanced. Sometimes there's just one answer (like a number), sometimes there's ID Answer, in other cases, there are multiple answers for one question (multi-select), sometimes I'm getting just bool and I need to render it to "Yes/No/I don't know" and other stuff like that
  2. Pipe that parses the object and renders it (but that will be neither easy nor clean, especially for multi-selects)
  3. Making different components for every possible type of answer - but that looks like an overkill.

CodePudding user response:

You can use {{ $any(answeredQuestion).answer.answerText }} to disable type checking for this. The $any() type cast function

  • Related