From c8ee01ec6d0dce25cac44339e9d962efae277b8b Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Thu, 1 Jul 2021 22:36:35 -0400 Subject: [PATCH] Assorted TS updates (#1750) --- .eslintrc | 5 +- src/connect/wrapMapToProps.ts | 3 +- src/types.ts | 257 ++++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+), 2 deletions(-) diff --git a/.eslintrc b/.eslintrc index 8745278a9..09dbe7f1e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -38,5 +38,8 @@ "react/jsx-wrap-multilines": 2, "react/no-string-refs": 0 }, - "plugins": ["@typescript-eslint", "import", "react"] + "plugins": ["@typescript-eslint", "import", "react"], + "globals": { + "JSX": true + } } diff --git a/src/connect/wrapMapToProps.ts b/src/connect/wrapMapToProps.ts index f2d5775eb..bb11089dc 100644 --- a/src/connect/wrapMapToProps.ts +++ b/src/connect/wrapMapToProps.ts @@ -9,6 +9,7 @@ type StateOrDispatch = S | Dispatch type AnyProps = { [key: string]: any } export type MapToProps

= { + // eslint-disable-next-line no-unused-vars (stateOrDispatch: StateOrDispatch, ownProps?: P): FixTypeLater dependsOnOwnProps?: boolean } @@ -18,7 +19,7 @@ export function wrapMapToPropsConstant( // It seems that the dispatch argument // could be a dispatch function in some cases (ex: whenMapDispatchToPropsIsMissing) // and a state object in some others (ex: whenMapStateToPropsIsMissing) - // + // eslint-disable-next-line no-unused-vars getConstant: (dispatch: Dispatch) => { dispatch?: Dispatch } ) { return function initConstantSelector(dispatch: Dispatch) { diff --git a/src/types.ts b/src/types.ts index e48206385..57ce0b42e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1 +1,258 @@ +/* eslint-disable no-unused-vars */ +// TODO Ignoring all unused variables for now + +import { + ClassAttributes, + Component, + ComponentClass, + ComponentType, + StatelessComponent, + Context, + NamedExoticComponent, +} from 'react' + +import { Action, ActionCreator, AnyAction, Dispatch, Store } from 'redux' + +// import hoistNonReactStatics = require('hoist-non-react-statics'); +import type { NonReactStatics } from 'hoist-non-react-statics' + export type FixTypeLater = any + +/** + * This interface can be augmented by users to add default types for the root state when + * using `react-redux`. + * Use module augmentation to append your own type definition in a your_custom_type.d.ts file. + * https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ +// tslint:disable-next-line:no-empty-interface +export interface DefaultRootState {} + +export type AnyIfEmpty = keyof T extends never ? any : T +export type RootStateOrAny = AnyIfEmpty + +// Omit taken from https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html +export type Omit = Pick> + +export type DistributiveOmit = T extends unknown + ? Omit + : never + +export interface DispatchProp { + dispatch: Dispatch +} + +export type AdvancedComponentDecorator = ( + component: ComponentType +) => NamedExoticComponent + +/** + * A property P will be present if: + * - it is present in DecorationTargetProps + * + * Its value will be dependent on the following conditions + * - if property P is present in InjectedProps and its definition extends the definition + * in DecorationTargetProps, then its definition will be that of DecorationTargetProps[P] + * - if property P is not present in InjectedProps then its definition will be that of + * DecorationTargetProps[P] + * - if property P is present in InjectedProps but does not extend the + * DecorationTargetProps[P] definition, its definition will be that of InjectedProps[P] + */ +export type Matching = { + [P in keyof DecorationTargetProps]: P extends keyof InjectedProps + ? InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : InjectedProps[P] + : DecorationTargetProps[P] +} + +/** + * a property P will be present if : + * - it is present in both DecorationTargetProps and InjectedProps + * - InjectedProps[P] can satisfy DecorationTargetProps[P] + * ie: decorated component can accept more types than decorator is injecting + * + * For decoration, inject props or ownProps are all optionally + * required by the decorated (right hand side) component. + * But any property required by the decorated component must be satisfied by the injected property. + */ +export type Shared = { + [P in Extract< + keyof InjectedProps, + keyof DecorationTargetProps + >]?: InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : never +} + +// Infers prop type from component C +export type GetProps = C extends ComponentType + ? C extends ComponentClass

+ ? ClassAttributes> & P + : P + : never + +// Applies LibraryManagedAttributes (proper handling of defaultProps +// and propTypes), as well as defines WrappedComponent. +export type ConnectedComponent< + C extends ComponentType, + P +> = NamedExoticComponent> & + NonReactStatics & { + WrappedComponent: C + } + +// Injects props and removes them from the prop requirements. +// Will not pass through the injected props if they are passed in during +// render. Also adds new prop requirements from TNeedsProps. +// Uses distributive omit to preserve discriminated unions part of original prop type +export type InferableComponentEnhancerWithProps = < + C extends ComponentType>> +>( + component: C +) => ConnectedComponent< + C, + DistributiveOmit, keyof Shared>> & + TNeedsProps +> + +// Injects props and removes them from the prop requirements. +// Will not pass through the injected props if they are passed in during +// render. +export type InferableComponentEnhancer< + TInjectedProps +> = InferableComponentEnhancerWithProps + +export type InferThunkActionCreatorType< + TActionCreator extends (...args: any[]) => any +> = TActionCreator extends ( + ...args: infer TParams +) => (...args: any[]) => infer TReturn + ? (...args: TParams) => TReturn + : TActionCreator + +export type HandleThunkActionCreator = TActionCreator extends ( + ...args: any[] +) => any + ? InferThunkActionCreatorType + : TActionCreator + +// redux-thunk middleware returns thunk's return value from dispatch call +// https://github.com/reduxjs/redux-thunk#composition +export type ResolveThunks = TDispatchProps extends { + [key: string]: any +} + ? { + [C in keyof TDispatchProps]: HandleThunkActionCreator + } + : TDispatchProps + +// the conditional type is to support TypeScript 3.0, which does not support mapping over tuples and arrays; +// once the typings are updated to at least TypeScript 3.1, a simple mapped type can replace this mess +export type ResolveArrayThunks< + TDispatchProps extends ReadonlyArray +> = TDispatchProps extends [ + infer A1, + infer A2, + infer A3, + infer A4, + infer A5, + infer A6, + infer A7, + infer A8, + infer A9 +] + ? [ + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator + ] + : TDispatchProps extends [ + infer A1, + infer A2, + infer A3, + infer A4, + infer A5, + infer A6, + infer A7, + infer A8 + ] + ? [ + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator + ] + : TDispatchProps extends [ + infer A1, + infer A2, + infer A3, + infer A4, + infer A5, + infer A6, + infer A7 + ] + ? [ + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator + ] + : TDispatchProps extends [ + infer A1, + infer A2, + infer A3, + infer A4, + infer A5, + infer A6 + ] + ? [ + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator + ] + : TDispatchProps extends [infer A1, infer A2, infer A3, infer A4, infer A5] + ? [ + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator + ] + : TDispatchProps extends [infer A1, infer A2, infer A3, infer A4] + ? [ + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator + ] + : TDispatchProps extends [infer A1, infer A2, infer A3] + ? [ + HandleThunkActionCreator, + HandleThunkActionCreator, + HandleThunkActionCreator + ] + : TDispatchProps extends [infer A1, infer A2] + ? [HandleThunkActionCreator, HandleThunkActionCreator] + : TDispatchProps extends [infer A1] + ? [HandleThunkActionCreator] + : TDispatchProps extends Array + ? Array> + : TDispatchProps extends ReadonlyArray + ? ReadonlyArray> + : never