type Action = { type: string }
export type ActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState) => R
type AsyncAcceptingDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: ActionThunk<R>): R;
<R, A extends Action>(thunk: A | ActionThunk<R>): A | R;
}
export type RegistryActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState, resourceRegistryId: string) => R
type RegistryActionCreator<R> = (...args: any[]) => (Action | RegistryActionThunk<R>)
type BoundRegistryActionCreator<F extends RegistryActionCreator<unknown>> =
ReturnType<F> extends RegistryActionThunk<unknown>
? (...args: Parameters<F>) => ReturnType<ReturnType<F>>
: F
type RegistryActionCreatorsMapObject = { [key: string]: RegistryActionCreator<unknown> }
type BoundRegistryActionCreatorsMapObject<TActionCreators extends RegistryActionCreatorsMapObject> = {
[TActionCreatorName in keyof TActionCreators]: BoundRegistryActionCreator<TActionCreators[TActionCreatorName]>
};
type RegistryDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: RegistryActionThunk<R>): R;
<R, A extends Action>(thunk: A | RegistryActionThunk<R>): A | R;
}
Types from actionUtils.ts
The basic stuff
type Action = { type: string }
export type ActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState) => R
type AsyncAcceptingDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: ActionThunk<R>): R;
<R, A extends Action>(thunk: A | ActionThunk<R>): A | R;
}
export type RegistryActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState, resourceRegistryId: string) => R
type RegistryActionCreator<R> = (...args: any[]) => (Action | RegistryActionThunk<R>)
type BoundRegistryActionCreator<F extends RegistryActionCreator<unknown>> =
ReturnType<F> extends RegistryActionThunk<unknown>
? (...args: Parameters<F>) => ReturnType<ReturnType<F>>
: F
type RegistryActionCreatorsMapObject = { [key: string]: RegistryActionCreator<unknown> }
type BoundRegistryActionCreatorsMapObject<TActionCreators extends RegistryActionCreatorsMapObject> = {
[TActionCreatorName in keyof TActionCreators]: BoundRegistryActionCreator<TActionCreators[TActionCreatorName]>
};
type RegistryDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: RegistryActionThunk<R>): R;
<R, A extends Action>(thunk: A | RegistryActionThunk<R>): A | R;
}
Overloads
type Action = { type: string }
export type ActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState) => R
type AsyncAcceptingDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: ActionThunk<R>): R;
<R, A extends Action>(thunk: A | ActionThunk<R>): A | R;
}
export type RegistryActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState, resourceRegistryId: string) => R
type RegistryActionCreator<R> = (...args: any[]) => (Action | RegistryActionThunk<R>)
type BoundRegistryActionCreator<F extends RegistryActionCreator<unknown>> =
ReturnType<F> extends RegistryActionThunk<unknown>
? (...args: Parameters<F>) => ReturnType<ReturnType<F>>
: F
type RegistryActionCreatorsMapObject = { [key: string]: RegistryActionCreator<unknown> }
type BoundRegistryActionCreatorsMapObject<TActionCreators extends RegistryActionCreatorsMapObject> = {
[TActionCreatorName in keyof TActionCreators]: BoundRegistryActionCreator<TActionCreators[TActionCreatorName]>
};
type RegistryDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: RegistryActionThunk<R>): R;
<R, A extends Action>(thunk: A | RegistryActionThunk<R>): A | R;
}
type Adder = {
(a: number, b: number): number;
}
type Adder2 = (a: number, b: number) => number;
namespace React {
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
}
Function objects
Overloads
function flip(n: number): number;
function flip(s: string): string;
function flip(x: number | string): number | string {
if (typeof x == "number") {
return -x;
}
return x;
}
type FlipType = {
(n: number): number;
(s: string): string;
(x: number | string): number | string
};
Task: Define the type for a function that returns string when called with a number and a number when called with a string
Registry stuff
type Action = { type: string }
export type ActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState) => R
type AsyncAcceptingDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: ActionThunk<R>): R;
<R, A extends Action>(thunk: A | ActionThunk<R>): A | R;
}
export type RegistryActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState, resourceRegistryId: string) => R
type RegistryActionCreator<R> = (...args: any[]) => (Action | RegistryActionThunk<R>)
type BoundRegistryActionCreator<F extends RegistryActionCreator<unknown>> =
ReturnType<F> extends RegistryActionThunk<unknown>
? (...args: Parameters<F>) => ReturnType<ReturnType<F>>
: F
type RegistryActionCreatorsMapObject = { [key: string]: RegistryActionCreator<unknown> }
type BoundRegistryActionCreatorsMapObject<TActionCreators extends RegistryActionCreatorsMapObject> = {
[TActionCreatorName in keyof TActionCreators]: BoundRegistryActionCreator<TActionCreators[TActionCreatorName]>
};
type RegistryDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: RegistryActionThunk<R>): R;
<R, A extends Action>(thunk: A | RegistryActionThunk<R>): A | R;
}
Increasing complexity
type ActionCreator<R> = (...args: any[]) => Action
type ReduxThunkActionCreator<R> = (...args: any[]) => (Action | ActionThunk<R>)
type RegistryActionCreator<R> = (...args: any[]) => (Action | RegistryActionThunk<R>)
Why export?
export type RegistryActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState, resourceRegistryId: string) => R
export function doSomething(/* ... */): RegistryActionThunk<Promise<ResourceState>> {
return somethingBeak({
// ...
});
}
Conditional Types
type Action = { type: string }
export type ActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState) => R
type AsyncAcceptingDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: ActionThunk<R>): R;
<R, A extends Action>(thunk: A | ActionThunk<R>): A | R;
}
export type RegistryActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState, resourceRegistryId: string) => R
type RegistryActionCreator<R> = (...args: any[]) => (Action | RegistryActionThunk<R>)
type BoundRegistryActionCreator<F extends RegistryActionCreator<unknown>> =
ReturnType<F> extends RegistryActionThunk<unknown>
? (...args: Parameters<F>) => ReturnType<ReturnType<F>>
: F
type RegistryActionCreatorsMapObject = { [key: string]: RegistryActionCreator<unknown> }
type BoundRegistryActionCreatorsMapObject<TActionCreators extends RegistryActionCreatorsMapObject> = {
[TActionCreatorName in keyof TActionCreators]: BoundRegistryActionCreator<TActionCreators[TActionCreatorName]>
};
type RegistryDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: RegistryActionThunk<R>): R;
<R, A extends Action>(thunk: A | RegistryActionThunk<R>): A | R;
}
T extends U ? X : Y
Index types and mapped types
type Action = { type: string }
export type ActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState) => R
type AsyncAcceptingDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: ActionThunk<R>): R;
<R, A extends Action>(thunk: A | ActionThunk<R>): A | R;
}
export type RegistryActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState, resourceRegistryId: string) => R
type RegistryActionCreator<R> = (...args: any[]) => (Action | RegistryActionThunk<R>)
type BoundRegistryActionCreator<F extends RegistryActionCreator<unknown>> =
ReturnType<F> extends RegistryActionThunk<unknown>
? (...args: Parameters<F>) => ReturnType<ReturnType<F>>
: F
type RegistryActionCreatorsMapObject = { [key: string]: RegistryActionCreator<unknown> }
type BoundRegistryActionCreatorsMapObject<TActionCreators extends RegistryActionCreatorsMapObject> = {
[TActionCreatorName in keyof TActionCreators]: BoundRegistryActionCreator<TActionCreators[TActionCreatorName]>
};
type RegistryDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: RegistryActionThunk<R>): R;
<R, A extends Action>(thunk: A | RegistryActionThunk<R>): A | R;
}
Index types and mapped types
type Names = { [key: string]: string };
function weird3<T extends {}>(arrs: T): { [K in keyof T]: number } {
// ...
}
weird3({ foo: "bar" }).foo
type Action = { type: string }
export type ActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState) => R
type AsyncAcceptingDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: ActionThunk<R>): R;
<R, A extends Action>(thunk: A | ActionThunk<R>): A | R;
}
export type RegistryActionThunk<R> =
(dispatch: AsyncAcceptingDispatch, getState: () => ReduxState, resourceRegistryId: string) => R
type RegistryActionCreator<R> = (...args: any[]) => (Action | RegistryActionThunk<R>)
type BoundRegistryActionCreator<F extends RegistryActionCreator<unknown>> =
ReturnType<F> extends RegistryActionThunk<unknown>
? (...args: Parameters<F>) => ReturnType<ReturnType<F>>
: F
type RegistryActionCreatorsMapObject = { [key: string]: RegistryActionCreator<unknown> }
type BoundRegistryActionCreatorsMapObject<TActionCreators extends RegistryActionCreatorsMapObject> = {
[TActionCreatorName in keyof TActionCreators]: BoundRegistryActionCreator<TActionCreators[TActionCreatorName]>
};
type RegistryDispatch = {
<A extends Action>(action: A): A;
<R>(thunk: RegistryActionThunk<R>): R;
<R, A extends Action>(thunk: A | RegistryActionThunk<R>): A | R;
}
Understanding actionUtils.ts
By Erik Vesteraas
Understanding actionUtils.ts
- 651