Propagate store enhancer generic type when using composeWithDevTools (#1323)

* Propagate store enhancer generic type when using composeWithDevTools

* Create silent-rats-tickle.md

* Update silent-rats-tickle.md
This commit is contained in:
Nathan Bierema 2023-01-08 19:56:45 -05:00 committed by GitHub
parent c72c021e2d
commit 07456db41e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 14 deletions

View File

@ -0,0 +1,5 @@
---
'@redux-devtools/extension': patch
---
Propagate store enhancer generic type when using composeWithDevTools

View File

@ -591,12 +591,25 @@ const preEnhancer =
} as any;
};
export type InferComposedStoreExt<StoreEnhancers> = StoreEnhancers extends [
infer HeadStoreEnhancer,
...infer RestStoreEnhancers
]
? HeadStoreEnhancer extends StoreEnhancer<infer StoreExt>
? StoreExt & InferComposedStoreExt<RestStoreEnhancers>
: never
: unknown;
const extensionCompose =
(config: Config) =>
(...funcs: StoreEnhancer[]): StoreEnhancer => {
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>> => {
// @ts-ignore FIXME
return (...args) => {
const instanceId = generateId(config.instanceId);
return [preEnhancer(instanceId), ...funcs].reduceRight(
// @ts-ignore FIXME
(composed, f) => f(composed),
__REDUX_DEVTOOLS_EXTENSION__({ ...config, instanceId })(...args)
);
@ -604,8 +617,12 @@ const extensionCompose =
};
interface ReduxDevtoolsExtensionCompose {
(config: Config): (...funcs: StoreEnhancer[]) => StoreEnhancer;
(...funcs: StoreEnhancer[]): StoreEnhancer;
(config: Config): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
}
declare global {
@ -616,18 +633,24 @@ declare global {
function reduxDevtoolsExtensionCompose(
config: Config
): (...funcs: StoreEnhancer[]) => StoreEnhancer;
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function reduxDevtoolsExtensionCompose<
StoreEnhancers extends readonly StoreEnhancer<unknown>[]
>(
...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function reduxDevtoolsExtensionCompose(
...funcs: StoreEnhancer[]
): StoreEnhancer;
function reduxDevtoolsExtensionCompose(...funcs: [Config] | StoreEnhancer[]) {
...funcs: [Config] | StoreEnhancer<unknown>[]
) {
if (funcs.length === 0) {
return __REDUX_DEVTOOLS_EXTENSION__();
}
if (funcs.length === 1 && typeof funcs[0] === 'object') {
return extensionCompose(funcs[0]);
}
return extensionCompose({})(...(funcs as StoreEnhancer[]));
return extensionCompose({})(...(funcs as StoreEnhancer<unknown>[]));
}
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = reduxDevtoolsExtensionCompose;

View File

@ -227,9 +227,22 @@ interface ReduxDevtoolsExtension {
connect: (preConfig: Config) => ConnectResponse;
}
export type InferComposedStoreExt<StoreEnhancers> = StoreEnhancers extends [
infer HeadStoreEnhancer,
...infer RestStoreEnhancers
]
? HeadStoreEnhancer extends StoreEnhancer<infer StoreExt>
? StoreExt & InferComposedStoreExt<RestStoreEnhancers>
: never
: unknown;
export interface ReduxDevtoolsExtensionCompose {
(config: Config): (...funcs: StoreEnhancer[]) => StoreEnhancer;
(...funcs: StoreEnhancer[]): StoreEnhancer;
(config: Config): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
}
declare global {
@ -241,12 +254,18 @@ declare global {
function extensionComposeStub(
config: Config
): (...funcs: StoreEnhancer[]) => StoreEnhancer;
function extensionComposeStub(...funcs: StoreEnhancer[]): StoreEnhancer;
function extensionComposeStub(...funcs: [Config] | StoreEnhancer[]) {
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>(
...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function extensionComposeStub<
StoreEnhancers extends readonly StoreEnhancer<unknown>[]
>(
...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function extensionComposeStub(...funcs: [Config] | StoreEnhancer<unknown>[]) {
if (funcs.length === 0) return undefined;
if (typeof funcs[0] === 'object') return compose;
return compose(...(funcs as StoreEnhancer[]));
return compose(...(funcs as StoreEnhancer<unknown>[]));
}
export const composeWithDevTools: ReduxDevtoolsExtensionCompose =