Error in TypeScript: Unable to assign type 'string' to type 'number | ""'

I am new to TypeScript and struggling to comprehend the error message below.

Type '{ order: string; }[]' is not compatible with type 'TestType[]'.
  Type '{ order: string; }' is not assignable to type 'TestType'.
    Types of property 'order' are conflicting.
      String type cannot be assigned to number or ''. 

This is the test code I have:

export enum ACTION_TYPES {
    TEST_ACTION = 'TEST_ACTION',
}

export type TestType = {
    order: number | '';
};

export function TestAction(
    testTypes: TestType[]
): {
    type: ACTION_TYPES.TEST_ACTION;
    testTypes: TestType[];
} {
    return {
        type: ACTION_TYPES.TEST_ACTION,
        testTypes,
    };
}

export type PluginsState = {
    testTypes: TestType[];
};

export type Actions =
    | ReturnType<typeof TestAction >;



const reducer = (
    state: PluginsState = {
        testTypes: [],
    },
    payload?: Actions
): PluginsState => {
    if ( payload && 'type' in payload ) {
        switch ( payload.type ) {
            case ACTION_TYPES.TEST_ACTION:
                return {
                    ...state,
                    testTypes: payload.testTypes,
                };
        }
    }
    return state;
};

export const stub = [
    {
		order: '',
    }
];


const defaultState: PluginsState = {
	testTypes: [],

};


reducer( defaultState, {
	type: ACTION_TYPES.TEST_ACTION,
	testTypes: stub,
} );

And here's the TypeScript playground link

The error originates from the last line testTypes: stub

I believe there may be a mistake on my end, but I'm unsure why '' cannot be utilized alongside number | ''

Is there a solution to this issue?

Answer №1

What you've written aligns with the author's perspective on the code, and it should function correctly. However, let's see how Typescript interprets it:

export const stub = [
    {
        order: '',
    }
];

In essence, this is of type: {order:string}[], which is generally suitable in most scenarios. Nevertheless, since this is a more generalized version of your specific {order:''}[], Typescript cannot ensure that any value passed will adhere to {order: number|''}. Even if you manipulate it, Typescript will have to permit it, hence the warning.

To prevent this inference, there are two options available:

  1. Explicitly specify the type for stub as TestType so TypeScript can prompt an error when it deviates from that type, like so:

    export const stub: TestType[] = [
      {
        order: "",
      },
    ] ;
    
  2. Alternatively, apply a const assertion to the mutable array elements to signify they remain unchanged, such as:

    export const stub = [
      {
        order: "",
      } as const,
    ] ;
    

You can view a functional example here: https://tsplay.dev/WvpdYN

Answer №2

When crafting the following code snippet:

export const stub = [
    {
        order: ''
    }
];

The compiler must determine the type of the variable stub. There are several possible types it could be inferred as (such as unknown, any, or Array<object>, and so on). So, the compiler employs heuristic rules to determine what it believes is most appropriate. In this instance, the inferred type is:

/* const stub: Array<{order: string}> */

This specifies an array of objects in no particular order, each of which must contain an order property with a value of type string. It's important to note that this is the type string, not the string literal type "". The selection of string over "" is often preferred since string values can be modified later on:

stub[0].order = "somethingElse"; // valid

However, if this is not the desired type, issues may arise when attempting to use it as an argument passed to the reducer() function, resulting in a compilation error.


To address this problem, you have two options: either explicitly provide a type annotation for the variable stub to specify the intended type:

export const stub: Array<TestType> = [ // annotated
    { order: '' }
]; 

reducer(defaultState, {
    type: ACTION_TYPES.TEST_ACTION,
    testTypes: stub, // valid
});

or alter how the value is inferred by the compiler, potentially by leveraging a const assertion to preserve "" as a string literal:

export const stub = [
    {
        order: '' as const, // assertion
    }
];
/* const stub: Array<{ order: ""; } */

reducer(defaultState, {
    type: ACTION_TYPES.TEST_ACTION,
    testTypes: stub,
});

Playground link to code

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

Establish HTTP headers for accessing the Oxford API in an Angular 6 application

public performAutocomplete(wordInput):any { let headersOptions = { headers:{ 'Accept': 'application/json', 'app_id': 'myid', "app_key": "mykey" } as any } this.wordTyped = wordInp ...

Ways to enhance focus on childNodes using Javascript

I am currently working on implementing a navigation system using a UL HTML Element. Here's the code I have so far: let htmlUL = <HTMLElement>document.getElementById('autocomplete_ul_' + this.name); if (arg.keyCode == 40) { // down a ...

What happens when arithmetic operators are applied to infinity values in JavaScript?

Why do Arithmetic Operators Behave Differently with Infinity in JavaScript? console.log(1.7976931348623157E+10308 + 1.7976931348623157E+10308)//Infinity console.log(1.7976931348623157E+10308 * 1.7976931348623157E+10308)//Infinity console.log(1.797693134 ...

What is the proper way to set up @Input?

I attempted to accomplish this in the following manner: @Input() data: any[] = []; Upon entering the ngOnInit lifecycle method, I notice that this.data is undefined: ngOnInit() { console.log(this.data); } Consequently, when trying to access th ...

What is the best way to restrict the key of an object type to only be within a specific union in TypeScript?

I need to create a set of server types in a union like this: type Union = 'A' | 'B' | 'C'; After that, I want to define an object type where the keys are limited to only certain options from this Union: // Use only 'A&ap ...

Exporting Typescript to Javascript files

I have created a sample TypeScript object with the following code: declare const S3 = "https://s3.amazonaws.com/xxx/icons"; declare const SVG = "svg-file-icons"; declare interface MyIcons { "image/jpeg": string; "image/jpg": string; } export const F ...

Can Nest.js providers be intercepted?

I'm attempting to intercept Nest.js providers using the methods outlined in the documentation, but it's not functioning as expected. Has anyone else experienced this issue? If so, is there a particular reason for this limitation? In general, I& ...

Issue: Pipe 'AsyncPipe' received an invalid argument '[object Object]'

I’m encountering an issue while attempting to replicate the steps from a specific YouTube tutorial. At the 8:22 mark of this video, I’m facing the following error: Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe&apos ...

Comparing the functions of useMemo and the combination of useEffect with useState

Is there a benefit in utilizing the useMemo hook instead of using a combination of useEffect and useState for a complex function call? Here are two custom hooks that seem to function similarly, with the only difference being that useMemo initially returns ...

how can I retrieve an array of nested objects from two interrelated tables that have a one-to-many relationship using

Hey everyone, I have a scenario where I'm working with 2 MySQL tables: itemsClass which holds various classes, and itemType which links to itemClass and contains type values for a specific class. My goal is to create a service that returns an Observa ...

A critical error has occurred: RangeError - The maximum call stack size has been exceeded while trying to

After attempting to filter a list of titles using Ng2SearchPipeModule, I imported the module in app.module.ts and created a new searchbar component. searchbar.component.ts import { FirebaseService } from './../../firebase.service'; import { Ang ...

Guide to creating the shared section of two wheels with CanvasRenderingContext2D

Is it possible to dynamically draw the shared area of two circular shapes using JavaScript and CanvasRenderingContext2D? My ultimate goal is to be able to adjust the size of the shape, ranging from a complete circle to a mere point. The desired outcome is ...

Having trouble handling responses in nodejs when using inversifyjs

Currently, I am utilizing nodejs alongside typescript, typeorm, and inversify for managing dependency injection. I am also using inversify express utils to handle controllers. However, I am facing an issue where sending a response inside the then or catch ...

Issues with Typescript function overloads when dealing with union types

I'm struggling to make function overloads work properly in TypeScript. My challenge involves a basic union type and a function that is capable of handling either type. I have defined overloads to deal with them separately. type A = { type: "a", x: n ...

Mastering the art of Promises and handling errors

I've been tasked with developing a WebApp using Angular, but I'm facing a challenge as the project involves Typescript and asynchronous programming, which are new to me. The prototype already exists, and it includes a handshake process that consi ...

Use the useEffect hook to pass newly updated data to a FlatList component

I have encountered an issue with updating a FlatList component in my React Native application. The scenario involves running a graphql query to render items and then refetching the data when a mutation is executed using Apollo's refetch option. Althou ...

Is it possible to set up VS Code's code completion feature to automatically accept punctuation suggestions?

For all the C# devs transitioning to TypeScript in VS Code, this question is directed at you. I was captivated by the code completion feature in VS C#. To paint a clearer picture, let's say I'm trying to write: console.log('hello') W ...

Angular Bootstrap Datepicker provides us with a date object, but I need it in the Date format

My desired date format is "Wed Aug 07 2019 16:42:07 GMT+0530 (India Standard Time)", but instead I am receiving { year: 1789, month: 7, day: 14 } from ngbDatepicker. Any assistance on resolving this issue would be greatly appreciated. ...

Dependency Injection: The constructor of the injectable class is called multiple times

There are multiple classes that inject the TermsExchangeService: import {TermsExchangeService} from './terms-exchange.service'; @injectable() export class TermsExchangeComponent { constructor( private termsExchangeService: TermsExchan ...

Using TypeScript to Trigger Events in Three.js

After recently diving into Typescript, I encountered an issue when using EventEmitter from the ThreeJS library. Whenever I attempt to trigger an event: const event: THREE.EventDispatcher = new THREE.EventDispatcher(); event.addEventListener('test&apo ...