How to manage undefined return type in Typescript?

Viewed 952

Sorry , I am new to Typescript, need to pass the prop to a component after filtering , for that I have defined a simple filter method. I get compilation error saying 'Type 'IMilestone[] | undefined' is not assignable to type 'IMilestone[]'

 const milestonesOfActiveGroup = ():IMilestone[] => {
    return studyProgress?.groups.filter((group:IGroup) => group.name === activeGroup)[0].milestones
  }

since I fetch and populate studyProgress it can be undefined right. What is the correct way to define this method?

3 Answers
const milestonesOfActiveGroup = (): IMilestone[] | undefined => {
    return studyProgress?.groups.filter((group:IGroup) => group.name === activeGroup)[0].milestones;
  }

You declared that "if studyProgress is undefined or null, returns undefined" (studyProgress?), so you should declare the return type with undefined (IMilestone[] | null). | is Union, whose meaning is "It will return IMilestone[] OR undefined".

You could defined it as IMilestone[] | undefined

const milestonesOfActiveGroup = (): IMilestone[] | undefined => {
    return studyProgress?.groups.filter((group:IGroup) => group.name === activeGroup)[0].milestones
  }

You used optional chaining on studyProgress, which means that variable may be null or undefined. In long form, your function does this:

const milestonesOfActiveGroup = (): IMilestone[] => {
  if (studyGroup) {
    return studyProgress.groups.filter(
      (group: IGroup) => group.name === activeGroup)[0].milestones
    )
  } else { 
    return undefined // this does not match the declared return type
  }
}

So if studyGroup does not exist, you can't drill into it and undefined is returned instead.

To handle this case you have a few options. Here's two.

Allow the function to return undefined

const milestonesOfActiveGroup = (): IMilestone[] | undefined => {

Or throw an error if studyProgress is really expected to be there, and if it's not there, then it should be considered a bug.

const milestonesOfActiveGroup = (): IMilestone[] => {
  if (!studyProgress) throw new Error("studyGroup has no value!")
  // typescript knows that studyProgress must exist from here on.
  return studyProgress.groups.filter((group:IGroup) => group.name === activeGroup)[0].milestones)
}

Think about what it means when studyProgress has no value set, and what you program should do in that case. Then handle that case and typescript should give you a green light.

Related