Bobby Wan-Kenobi
Bobby Wan-Kenobi

Reputation: 925

Rewriting function in TypeScript

I have the following (working) function in JavaScript:

function solve(strArr) {
  return strArr.reduce(function ([x, y], curr) {
    switch (curr) {
      case 'up':    return [x, y + 1]
      case 'down':  return [x, y - 1]
      case 'left':  return [x - 1, y]
      case 'right': return [x + 1, y]
    }
  }, [0, 0])
}

I'm trying to rewrite it using TypeScript as:

function solve(strArr: string[]): number[] {
  return strArr.reduce(([x, y]: number[], curr: string) =>  {
    switch (curr) {
      case 'up': return [x, y + 1]
      case 'down': return [x, y - 1]
      case 'left': return [x - 1, y]
      case 'right': return [x + 1, y]
    }
  }, [0,0])
}

but I'm getting the Type 'string' is not assignable to type 'number[]'. error, which I know refers to the accumulator, but don't know how to solve.

As per Rajesh's suggestion, changing the type of strArr to any solves the issue, but giving it the specific type I'm using with the function doesn't work; why?

Upvotes: 3

Views: 191

Answers (4)

Yukulélé
Yukulélé

Reputation: 17112

You can improve params and return types.

For the code's readability, you should avoid array.reduce().

type Direction = 'up' | 'down' | 'left' | 'right'
function solve(directions: Direction[]): [number, number] {
  let x = 0
  let y = 0
  for (const direction of directions) {
    switch (direction) {
      case 'up': y++; break
      case 'down': y--; break
      case 'left': x--; break
      case 'right': x++; break
    }
  }
  return [x, y]
}

Upvotes: 0

TmTron
TmTron

Reputation: 19441

You should explicitly handle the default case in your switch:

function solve(strArr:string[]) {
  return strArr.reduce(([x, y], curr) =>  {
    switch (curr) {
      case 'up': return [x, y + 1]
      case 'down': return [x, y - 1]
      case 'left': return [x - 1, y]
      case 'right': return [x + 1, y]
      // maybe throw an error instead
      default: return [x, y];
    }
  }, [0,0])
}

Playground example

without the default case your reducer function returns the type: number[] | undefined

Upvotes: 1

Roberto Zvjerković
Roberto Zvjerković

Reputation: 10157

You can add a default case for your switch as others have suggested.

I would advise a second solution, which is to create a type for your input parameter to narrow the type:

type Direction = 'up' | 'down' | 'left' | 'right'

function solve(strArr: Direction[]) {
  return strArr.reduce(([x, y], curr) =>  {
    switch (curr) {
      case 'up': return [x, y + 1]
      case 'down': return [x, y - 1]
      case 'left': return [x - 1, y]
      case 'right': return [x + 1, y]
    }
  }, [0,0])
}

Play

Upvotes: 3

Rajesh Kanna
Rajesh Kanna

Reputation: 143

Because you are not covering all cases.

Add the default case to the switch

default : return []

Upvotes: -3

Related Questions