Search code examples
angulartypescriptlambdastrong-typing

Angular/Typescript: declare return type of lambda passed to "find"


So, I am following a training course and have an Angular service:

import {Exercise} from "./exercise.model";

export class TrainingService{
  private availableExercises: Exercise[] = [
    { id: 'crunches', name: 'Crunches', duration: 30, calories: 8 },
    { id: 'touch-toes', name: 'Touch Toes', duration: 180, calories: 15 },
    { id: 'side-lunges', name: 'Side Lunges', duration: 120, calories: 18 },
    { id: 'burpees', name: 'Burpees', duration: 60, calories: 8 }
  ];

  private currentExercise: Exercise | null = null;

  getAvailableExercises() : Exercise[] {
    return this.availableExercises.slice();   //// slice() returns a copy (new object), not a reference
  }

  startExercise(exerciseId: string) : void {
    this.currentExercise = this.availableExercises.find( (exercise: Exercise) : Exercise | null => 
        {exercise.id === exerciseId});
  }

}

I just added startExercise)() and get an error. I can, of course, recode it not to use find(), but would prefer to know what is happening here. Coming from a strongly typed language background, I have enforced type checking.

The specific error is

  Type 'undefined' is not assignable to type 'Exercise | null'.

18     this.currentExercise = this.availableExercises.find( (exercise: Exercise) : Exercise | null => {exercise.id === exerciseId});
       ~~~~~~~~~~~~~~~~~~~~


Error: src/app/training/training.service.ts:18:81 - error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.

18     this.currentExercise = this.availableExercises.find( (exercise: Exercise) : Exercise | null => {exercise.id === exerciseId});

How do I fix that code?


Solution

  • The typescript compiler knows the array AvailableExercises is of type Exercise[], so you actually dont have to define the (exercise: Exercise) : Exercise | null again as type Exercise.

    Just putting:

    this.currentExercise = this.availableExercises.find(exercise => exercise.id === exerciseId); 
    

    Should already be working. You can check if it found anything as array.find will return the first element where the predicate is true and undefined otherwise. So

    if (!this.currentExercise) {
       // Here some error or your own idea
    }
    

    Op here, apologies for editing the answer, but I can't really code format in commants.

    1. private currentExercise: Exercise | undefined;

    2. this.currentExercise = this.availableExercises.find( (exercise: Exercise) => {exercise.id === exerciseId}); and it works