Display Name
Display Name

Reputation: 15091

How to fix "TodoItem undefined is not assignable to type TodoItem" error?

I am learning TypeScript.

The contents of todoItem.ts:

export class TodoItem {
  constructor(
    public id: number,
    public task: string,
    public complete: boolean = false
  ) {}

  printDetails(): void {
    console.log(
      `${this.id}\t${this.task} ${this.complete ? "\t(complete)" : ""}`
    );
  }
}

The contents of todoCollection.ts:

import { TodoItem } from "./todoItem";

export class TodoCollection {
  private nextId: number = 1;

  constructor(public userName: string, public todoItems: TodoItem[] = []) {}

  addTodo(task: string): number {
    while (this.getTodoById(this.nextId)) {
      this.nextId++;
    }
    this.todoItems.push(new TodoItem(this.nextId, task));
    return this.nextId;
  }

  getTodoById(id: number): TodoItem {
    return this.todoItems.find((item) => item.id === id);
  }
}

When compiling with tsc, I get the following error:

src/todoCollection.ts:17:5 - error TS2322: Type 'TodoItem | undefined' is not assignable to type 'TodoItem'. Type 'undefined' is not assignable to type 'TodoItem'.

17 return this.todoItems.find((item) => item.id === id); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Found 1 error.

Question

How to fix this error? I really have no idea because I cannot spot any peculiarity. Everything looks fine.

Upvotes: 1

Views: 175

Answers (1)

CollinD
CollinD

Reputation: 7573

Array#find may return undefined if the predicate function does not return a truthy value for any element of the array. Typescript is complaining because you've told it you will be returning a TodoItem in the method header, but you actually attempted to return something that might be a TodoItem or might be undefined (as far as static analysis can tell).

You have a few options on how to resolve this:

  1. Add | undefined to your return type, eg
getTodoById(id: number): TodoItem | undefined {
  1. Add some other flow control when the item isn't found, such as throwing an exception
getTodoById(id: number): TodoItem {
  const result = this.todoItems.find(item => item.id === id)
  if (!result) {
    throw new Error("Not Found!");
  }
  return result;
}
  1. Use the not-null assertion operator. If you know for a fact that this will always find a result, you can simply tell TS that the return value will never be null or undefind by using the ! postfix operator.
return this.todoItems.find(item => item.id === id)!
  1. Disable strict null checks in your ts config. I don't recommend this option, but typescript can be used for as little or as much as you'd like by configuring options in tsconfig.json.

Upvotes: 1

Related Questions