Revamping code in TypeScript

I have a function in JavaScript that is working properly:

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])
}

Now I am attempting to rewrite the function using TypeScript like this:

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])
}

However, I am encountering an error message

Type 'string' is not assignable to type 'number[]'
, specifically related to the accumulator. I am unsure of how to resolve this issue.

Following a suggestion from Rajesh on StackOverflow, changing the type of strArr to any does solve the error. However, providing it with the specific type used in the function does not work. I'm curious why this is the case.

Answer №1

One suggestion is to include a default case in your switch statement.

Another approach would be to define a custom type for the input parameter to narrow down the options:

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])
}

Check it out on TypeScript Playground

Answer №2

It is important to handle the default case explicitly in a switch statement:

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]
      // It might be advisable to throw an error instead
      default: return [x, y];
    }
  }, [0,0])
}

Example in Playground

If the default case is not handled in your reducer function, it may return the type: number[] | undefined

Answer №3

Enhancing parameters and output types can lead to better code functionality.

To enhance the clarity of the code, it is recommended to refrain from using array.reduce().

type Direction = 'up' | 'down' | 'left' | 'right'
function calculatePosition(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]
}

Answer №4

It seems that you may have overlooked some cases.

To ensure completeness, consider adding a default case to the switch statement:

default : return []

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How is it possible for the output to be a string array when the variable was declared as a number in TypeScript?

Snippet: function sampleFunction(sample:string|number|string[]) { if(typeof sample == "string") { console.log("Sample is String " + sample); } else if(typeof sample == "number") { console.log("Sample is Number " + sampl ...

Insert information into a 3-tiered nested Angular FormArray within interconnected dropdown fields

After trying to retrieve data from an API call to populate a select form field, I encountered difficulties setting the value correctly using a FormArray. This led me to creating a FormArray with 3 nested levels in Angular, taking reference from this examp ...

Implementing Dependent Props in React using Typescript

I have created a custom Button React Component: function Button({ text, Icon, iconProps, ...buttonProps }: ButtonProps) The properties for this component must adhere to the following rules: Only contain a text Only include an Icon An Icon along with icon ...

Tips for merging arrays conditionally in JavaScript

Currently facing a dilemma without a clear solution, aiming to provide minimal context and focus solely on the problem at hand A worker logs their daily hours at work, stored in the "dayli_data" array. If the worker misses logging hours, it triggers the " ...

I'm seeking assistance in grasping the concept of the useState generic definition. Can anyone help

I recently came across a new definition for useState generics in a TS course, but it was briefly covered and I'm still struggling to fully grasp it. function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>&g ...

Issues with typescript compiler when using React-beautiful-dnd

I recently updated react and react-beautiful-dnd to the newest versions and now I am encountering many type errors in my code: {sortedDimensions.map((dimension: any, index: number) => ( <Draggable key={index} ...

Date selection feature in Material UI causing application malfunction when using defaultValue attribute with Typescript

Recently, I discovered the amazing functionality of the Material UI library and decided to try out their date pickers. Everything seemed fine at first, but now I'm facing an issue that has left me puzzled. Below is a snippet of my code (which closely ...

Error in Angular 7: Trying to assign a 'void' type to a 'ObservableInput<{}>' type

I can't seem to understand why I am encountering this error fetchFromURL(url: string): any { return this.apiService.get(url).pipe(map(data => data)); } fetchNextPage(): Observable<any> { const url = 'url'; this.f ...

I noticed that when using Next.js with the `revalidate: 1` option on a static page, it is triggering two full F5 refresh actions instead of just one. I was hoping for

Currently, I have set up a blog post edit page in my Next.js project. The post pages are utilizing the Incremental Static Regeneration feature with a revalidation time of 1 second for testing purposes. In the future, I plan to increase this to a revalidat ...

Revise the classification of an instance variable within a subclass

I am pondering about the topic of inheritance and types for instance variables in typescript. Consider a basic class as shown below: class Person { instanceVariable: Object; age: Number; constructor(instanceVariable: Object, age: Number) { this ...

The conditional type in TypeScript is malfunctioning

Upon finishing an article discussing conditional types in TypeScript located at: I have attempted to implement a conditional type in the following function: function convertToIsoString<T extends number|undefined>( timestamp:T ): T extends number ...

Retrieve the API output and save the information into an array

I am struggling with calling an API in my Angular application and extracting specific data from the JSON response to populate an array. Although I am able to retrieve the response, I am having trouble isolating a particular field and storing it in an array ...

Guide on invoking child components' functions from the parent component in Angular 6

Main Component import { Component } from '@angular/core'; import { DisplayComponent } from './display.component'; @Component({ selector: 'my-app', template: ` <button (click)="submit()">Call Child Com ...

Updating the default value for react-i18next (stored in localstorage)

When utilizing a backend and language detector, an issue arises: The localstorage contains the key I18nextLng with the value en-US. How can we set the default value to be I18nextLng with the value En? init and other settings are as per the default docume ...

What is the reason behind Typescript's discomfort with utilizing a basic object as an interface containing exclusively optional properties?

Trying to create a mock for uirouter's StateService has been a bit challenging for me. This is what I have attempted: beforeEach(() => { stateService = jasmine.createSpyObj('StateService', ['go']) as StateService; } ... it(& ...

Combining tuples with their corresponding data types

Trying to define a new type: type Union = [1, "one"] | [1, "first"] | [2, "two"] type GetTuple<T, U> = Extract<T, [U, ...unknown[]]>; type ObjectFromUnion<T extends Union[0] = Union[0]> = { number: T, word: ?? } Looking to utiliz ...

Guide to accessing the content of pure ES6 modules directly in the Chrome console without the need for Webpack

Situation: When using tsc to compile code for es6, the scripts function properly once they are served from a server. However, I am unsure of how to access variables within modules through the console. The file names do not seem to be available as objects ...

What is the proper way to terminate a Promise.all() in Angular 2?

My current sign-up process involves a Promise.all() being made on every "next" click, resulting in multiple http requests. However, when users quickly click through the process, these requests start to pile up and cause issues with my app. Is there a way ...

Issue with Readonly modifier not functioning as expected in Angular/Typescript

My goal is to create a component property that is read-only. However, I am facing an issue where the readonly modifier does not seem to have any effect. View example on stackblitz According to the documentation, once I initialize the cars property in the ...

What is the best way to locate an item within a Redux array when working with TypeScript?

Below is the content of my slice.ts file. interface iItem { Category: string; Id: string; } interface iDataState { Items: Array<iItem>; } const initialState: iDataState = { Items: [], }; reducers: { updateItem: (state, action: PayloadAc ...