fix(typings): make 'status' state slice more typesafe (#4709)

This commit is contained in:
Vladislav Shkodin 2020-12-15 12:38:59 +02:00 committed by GitHub
parent 92a3bfa485
commit df97aec9aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 26 deletions

View File

@ -13,7 +13,7 @@ export const STATUS_FAILURE = 'STATUS_FAILURE';
export function statusRequest() { export function statusRequest() {
return { return {
type: STATUS_REQUEST, type: STATUS_REQUEST,
}; } as const;
} }
export function statusSuccess(status: { export function statusSuccess(status: {
@ -23,21 +23,21 @@ export function statusSuccess(status: {
return { return {
type: STATUS_SUCCESS, type: STATUS_SUCCESS,
payload: { status }, payload: { status },
}; } as const;
} }
export function statusFailure(error: Error) { export function statusFailure(error: Error) {
return { return {
type: STATUS_FAILURE, type: STATUS_FAILURE,
payload: { error }, payload: { error },
}; } as const;
} }
export function checkBackendStatus() { export function checkBackendStatus() {
return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => { return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
try { try {
const state = getState(); const state = getState();
if (state.status.get('isFetching') === true) { if (state.status.get('isFetching')) {
return; return;
} }
@ -90,3 +90,7 @@ export function checkBackendStatus() {
} }
}; };
} }
export type StatusAction = ReturnType<
typeof statusRequest | typeof statusSuccess | typeof statusFailure
>;

View File

@ -334,11 +334,11 @@ export class Backend {
auth: { status: boolean }; auth: { status: boolean };
api: { status: boolean; statusPage: string }; api: { status: boolean; statusPage: string };
} = { } = {
auth: { status: false }, auth: { status: true },
api: { status: false, statusPage: '' }, api: { status: true, statusPage: '' },
}; };
for (let i = 1; i <= attempts; i++) { for (let i = 1; i <= attempts; i++) {
status = await this.implementation!.status(); status = await this.implementation.status();
// return on first success // return on first success
if (Object.values(status).every(s => s.status === true)) { if (Object.values(status).every(s => s.status === true)) {
return status; return status;

View File

@ -20,9 +20,9 @@ export const defaultState = fromJS({
isFetching: false, isFetching: false,
user: undefined, user: undefined,
error: undefined, error: undefined,
}); }) as Auth;
const auth = (state = defaultState as Auth, action: AuthAction) => { const auth = (state = defaultState, action: AuthAction) => {
switch (action.type) { switch (action.type) {
case AUTH_REQUEST: case AUTH_REQUEST:
return state.set('isFetching', true); return state.set('isFetching', true);

View File

@ -1,16 +1,26 @@
import { Map, fromJS } from 'immutable'; import { fromJS } from 'immutable';
import { AnyAction } from 'redux'; import { STATUS_REQUEST, STATUS_SUCCESS, STATUS_FAILURE, StatusAction } from '../actions/status';
import { STATUS_REQUEST, STATUS_SUCCESS, STATUS_FAILURE } from '../actions/status'; import { StaticallyTypedRecord } from '../types/immutable';
import { Status } from '../types/redux';
interface StatusAction extends AnyAction { export type Status = StaticallyTypedRecord<{
payload: { isFetching: boolean;
status: { auth: { status: boolean }; api: { status: boolean; statusPage: string } }; status: StaticallyTypedRecord<{
error?: Error; auth: StaticallyTypedRecord<{ status: boolean }>;
}; api: StaticallyTypedRecord<{ status: boolean; statusPage: string }>;
} }>;
error: Error | undefined;
}>;
const status = (state = Map(), action: StatusAction) => { const defaultState = fromJS({
isFetching: false,
status: {
auth: { status: true },
api: { status: true, statusPage: '' },
},
error: undefined,
}) as Status;
const status = (state = defaultState, action: StatusAction) => {
switch (action.type) { switch (action.type) {
case STATUS_REQUEST: case STATUS_REQUEST:
return state.set('isFetching', true); return state.set('isFetching', true);
@ -30,7 +40,7 @@ const status = (state = Map(), action: StatusAction) => {
}; };
export const selectStatus = (status: Status) => { export const selectStatus = (status: Status) => {
return status.get('status')?.toJS() || {}; return status.get('status').toJS();
}; };
export default status; export default status;

View File

@ -35,4 +35,5 @@ export interface StaticallyTypedRecord<T> {
mapFunc: (value: T[K]) => V, mapFunc: (value: T[K]) => V,
): StaticallyTypedRecord<{ [key: string]: V }>; ): StaticallyTypedRecord<{ [key: string]: V }>;
keySeq<K extends keyof T>(): { toArray: () => K[] }; keySeq<K extends keyof T>(): { toArray: () => K[] };
withMutations(mutator: (mutable: StaticallyTypedRecord<T>) => unknown): StaticallyTypedRecord<T>;
} }

View File

@ -4,6 +4,7 @@ import { Map, List, OrderedMap, Set } from 'immutable';
import AssetProxy from '../valueObjects/AssetProxy'; import AssetProxy from '../valueObjects/AssetProxy';
import { MediaFile as BackendMediaFile } from '../backend'; import { MediaFile as BackendMediaFile } from '../backend';
import { Auth } from '../reducers/auth'; import { Auth } from '../reducers/auth';
import { Status } from '../reducers/status';
export type SlugConfig = StaticallyTypedRecord<{ export type SlugConfig = StaticallyTypedRecord<{
encoding: string; encoding: string;
@ -290,11 +291,6 @@ export type Search = StaticallyTypedRecord<{
export type Cursors = StaticallyTypedRecord<{}>; export type Cursors = StaticallyTypedRecord<{}>;
export type Status = StaticallyTypedRecord<{
isFetching: boolean;
status: StaticallyTypedRecord<{ auth: boolean }>;
}>;
export interface State { export interface State {
auth: Auth; auth: Auth;
config: Config; config: Config;