Ошибка машинописного текста "Свойство then" не существует "при объединении обещаний с обещанием связующего ПО + thunk
Я использую промежуточное программное обеспечение redux-обещание с redux-thunk, чтобы связать мои обещания:
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); // this works
});
}
}
Приведенный выше код работает, но также генерирует предупреждение во время компиляции:
TS2339: свойство 'then' не существует для типа '{ type: string; полезная нагрузка: Promise<{}>; }"
Похоже, мне нужно включить Promise<...>
где-то как тип, так что машинопись знает, что then
на самом деле это свойство объекта, который возвращается dispatcher()
но я не смог удалить ошибку.
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();
// Create myThunkAction function with a type of ThunkAction<R, S, E>
let myThunkAction: ThunkAction<Promise<string>, IState, null> =
(dispatch: Dispatch<IState>, getState: () => IState) => {
return new Promise<string>((resolve, reject) => {
// do async stuff with getState() and dispatch(), then...
resolve('done!');
});
}
store.dispatch(myThunkAction)
.then(() => {
// do stuff after the thunk has finished...
});
Кажется связанным, но где я могу указать тип действия, т.е. MY_ACTION
?
1 ответ
Как вы можете видеть на этой детской площадке a
выставляет те же ключи, что и типDispatch<any>
и, как вы можете видеть, если навести курсор мыши на ошибку, сообщение об ошибке будет таким же, как и в вашем случае. Для того, чтобы получить доступ к обещанию (и там для then
функция) вам придется получить доступ к payload
объекта отправки.
this.dispatcher({ ... }).payload.then(....);
Edit1:
Если мы посмотрим на типизацию для redux, то сможем довольно быстро найти интерфейс Dispatcher.
export interface Dispatch<S> {
<A extends Action>(action: A): A;
}
export interface Action {
type: any;
}
И затем с помощью некоторого переписывания и некоторого либерального использования псевдокода мы можем вывести, что тип Dispatch - это функция, которая принимает один аргумент, а не объект, и возвращает объект того же типа, что и аргумент.
type Dispatch: (action: {type: any, ...}) => {type: any, ...}
И входной объект, и выходной объект имеют тип:
interface {
type: any,
[key: string]: value
}
В заключение, либо: 1) вы не используете официальные типизации для redux, 2) официальные типизации для redux неверны, либо 3) вы что-то упустили в своей среде, в действительности код не работает.
Edit2:
Я не пробовал этот код, поэтому я понятия не имею, решит ли он вашу проблему. Но вы можете попытаться переопределить интерфейс Dispatch.
declare module 'redux' {
export interface Action {
type: any;
}
export interface Dispatch<S> {
<A extends Action>(action: A): Promise<S>;
}
}
Это действительная машинопись, как вы можете видеть на этой игровой площадке, но мне раньше не приходилось делать это самостоятельно, так что это может не сработать.
Если это не сработает, вы можете попробовать определить пространство имен с тем же именем, что и у модуля.
namespace redux {
export interface Action {
type: any;
}
export interface Dispatch<S> {
<A extends Action>(action: A): Promise<S>;
}
}
Тем не менее, я не пробовал это раньше, поэтому я не могу гарантировать, что это будет работать.