Encountering a Typescript issue stating "Property 'then' does not exist" while attempting to chain promises using promise-middleware and thunk

Currently, I am utilizing redux-promise-middleware alongside redux-thunk to effectively chain my promises:

import { Dispatch } from 'redux';

class Actions {
    private static _dispatcher: Dispatch<any>;
    public static get dispatcher(): Dispatch<any> {
        return Actions._dispatcher;
    }
    public static test() {
        this.dispatcher({
            type: 'MY_ACTION',
            payload: new Promise(resolve => resolve('hi'));
        }).then(result => {
            console.log(result); // It's working fine
        });
    }
}

The code snippet above is functional but triggers a warning message during compilation:

TS2339: Property 'then' does not exist on type '{ type: string; payload: Promise<{}>; }'

It appears that I must include Promise<...> somewhere as a type so TypeScript recognizes that then is indeed a property of the object returned by dispatcher(). Despite my efforts, I have yet to resolve this error.

https://github.com/gaearon/redux-thunk/issues/103

import { Dispatch } from 'redux';
import { ThunkAction } from 'redux-thunk';
import { getStore, IState } from './my_store';

let store = getStore();

// Define myThunkAction function with type ThunkAction<R, S, E>
let myThunkAction: ThunkAction<Promise<string>, IState, null> =
    (dispatch: Dispatch<IState>, getState: () => IState) => {
        return new Promise<string>((resolve, reject) => {

            // Perform asynchronous operations using getState() and dispatch(), then...
            resolve('done!');

        });
    }

store.dispatch(myThunkAction)
.then(() => {
    // Execute actions after the thunk has completed...
});

This seems relevant, but where should I specify the action type, for example, MY_ACTION?

Answer №1

Upon examining this TypeScript playground example, it is evident that the variable a shares the same keys as the type of Dispatch<any>. If you hover over the error, you'll notice that the error message aligns with your situation. To access the promise and utilize the then function, you need to retrieve the payload from the Dispatch object.

this.dispatcher({ ... }).payload.then(....);

Edit1:

A quick review of the redux typings on GitHub reveals the Dispatcher interface.

export interface Dispatch<S> {
    <A extends Action>(action: A): A;
}
export interface Action {
  type: any;
} 

By rearranging and using pseudocode liberally, we can infer that the Dispatch type is a function that takes an object argument and returns an object of the same type.

type Dispatch: (action: {type: any, ...}) => {type: any, ...}

Both the input and output objects adhere to this structure:

interface {
    type: any,
    [key: string]: value
}

In conclusion, the issue could stem from either 1) not using official redux typings, 2) errors in the official typings, or 3) overlooked details in the live environment where the code fails to work.

Edit2:

I have not tested this code, so I cannot guarantee its effectiveness in resolving your problem. One approach could involve redefining the Dispatch interface.

declare module 'redux' {
    export interface Action {
       type: any;
    }
    export interface Dispatch<S> {
        <A extends Action>(action: A): Promise<S>;
    }
}

This TypeScript snippet is valid, as demonstrated in this playground. However, since I haven't personally encountered this scenario before, there may be potential issues implementing it.

If the above method does not work, another option is defining a namespace with the identical name as the module.

namespace redux {
    export interface Action {
       type: any;
    }
    export interface Dispatch<S> {
        <A extends Action>(action: A): Promise<S>;
    }
}

As I have not experimented with this approach previously, I cannot assure its success.

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

Struggling with organizing my code in node.js - it's all over the place and not very reliable. How should I tackle this

Can anyone help me troubleshoot an issue I'm facing with code that writes to the console late or in random order? var request = require('request'); var vFind = 'HelloWorld'; var vFound = false; var vSites = ['http://www.youtu ...

Encountering an issue when trying to generate a button in Angular

I am currently using JavaScript to dynamically create a button in Angular. While I have been successful in creating the button, I am encountering an error when attempting to change the classname. The error message I am receiving is: Property 'clas ...

Is there a way to prompt TypeScript to report an error when a mapped key is missing?

Here is my current code snippet: type TransferType = 'INTERNAL' | 'WITHDRAWAL' | 'DEPOSIT' type TransferEvents = Record<TransferType, Record<string, TypeFoo | TypeBar>> export interface EventsTooltip extends Tran ...

Tips for accessing a value in a multidimensional json array without the key in JavaScript/jQuery?

I'm working with a JSON file that contains a multidimensional array. The array consists of city data at the first level and temperature data at the second level. I'm facing difficulties in dynamically extracting values from the second level. I a ...

Getting the response data from an XMLHttpRequest - Full guide with screenshots

Currently, I am working with autocomplete jQueryUI and have this code snippet: .autocomplete({ source: function( request, response ) { var results = $.getJSON( url, { term: extractLast( request.term ) }, response ); console.log(results); ...

Choosing the content within a div and inserting it into an email

I have an email sender feature on my website where users can fill out input fields and hit send, resulting in me receiving an email. The text from all the input boxes is included in the email body. Additionally, there are some generated texts in divs with ...

In JavaScript, the return statement is used to halt the execution of any subsequent statements

I encountered a situation where I need to stop the execution of the next function call if the previous function has a return statement. However, I noticed that even though there is a return statement in the "b" function below, the next function call still ...

Issue with Jquery event not triggering correctly following ajax data retrieval

This script uses jQuery and Ajax to populate a navigation bar with categories and subcategories dynamically. The first unordered list is static, while the second one is populated after receiving data via Ajax. There are some jQuery events that need to be i ...

Creating unit tests without relying on a testing framework: A guide

My goal is to unit test a simple function using pure JavaScript: NS.isType = function (type, obj) { if (obj.constructor && obj.constructor.name) { return obj.constructor.name === type; } return toString.call(obj) === '[obj ...

The element of type 'OverridableComponent<LinkTypeMap<{}, "a">>' cannot be assigned to a 'ReactNode'

I'm currently working on a project where there's a component named ListItemTextStyle. Within that component, the prop type is defined as follows: import { LinkProps, ListItemButtonProps, } from '@mui/material'; type IProps = LinkP ...

Record the marker's location only once following the completion of its dragging action

Is there a way to make the console log for getPosition only happen when the marker is stopped being dragged, rather than every 0.1 seconds while it's being dragged? Similar to how .getRadius() works - it logs the radius change just once. https://i.ss ...

The optimal method for designing a select menu to ensure it works smoothly on various web browsers

Recently, I encountered an issue with customizing a select menu using CSS and jQuery. After some work, I was able to achieve a result that I am quite pleased with: So far, the styling works perfectly in Mozilla, Opera, Chrome, and IE7+. Below is the curr ...

Utilize jQuery Function on Identical Class of <ul> Elements

I have integrated a listview control in my ASPX page. The data is being fetched from the database and displayed in the listview. I have also utilized jQuery script to implement the .fadein() and .fadeout() effects on the listview elements. However, when I ...

Setting a checkbox to true within the MUI Data Grid using my input onChange event - how can I achieve this?

I am looking to highlight the selected row in my usage input onChange event. https://i.stack.imgur.com/rp9rW.png Details of Columns: const columns = [ { field: 'part_code', headerName: 'Part Code', width: 200 }, { ...

The presence of a .js file is causing a blockage in the loading

As a beginner in the world of jquery/web design, I decided to download a template to experiment and get more familiar with it. Unfortunately, I encountered an issue with a specific script that is causing my jQuery to not load properly. Here is the snippet ...

Displaying content on a webpage using PHP, AJAX, and HTML

Looking to update my current form setup. I have a basic Form below: <form action="" method="POST"> <input type="button" value="Generate Numbers" onclick="on_callPhp1()"/> </form> Accompanied by this javascript code: <script type="te ...

Unable to proceed with entering subsequent values into the input field after the initial input in reactjs

Issue with login form: Unable to provide second value after entering the first one. The text input field does not allow for entering more than one value before completing the existing entry. import React, { useCallback } from 'react'; import { Te ...

Which is more efficient in JavaScript: Arrays, Object literals, or JSON for achieving better performance?

I'm facing a tough decision in choosing the most effective option. Currently, I have a simple array set up like this: var array = [ '/index1.html', '/index2.html', '/index3.html' ]; While this array consists ...

Error: $controller does not function as a controller within another controller

I recently started learning Angular JS and attempted to call one controller within another, but encountered the following error: ionic.bundle.js:21157 TypeError: $controller is not a function at new <anonymous> (http://localhost:8080/itravel/www/js/ ...

What is the best method for eliminating the default title in selectpicker?

I'm currently working on integrating angular selectpicker into my project. Initially, everything was displaying correctly as shown below: <select class="selectpicker"> <option>Mustard</option> <option>Ketchup</opti ...