Compiler fails to infer one specific type with dynamic selector

1 day ago 5
ARTICLE AD BOX

I have this enum:

export enum SOME_TYPES { foo = 'foo' fooBar = 'fooBar' bar = 'bar' }

and this is a registry I am writing:

export const myRegistry = { [SOME_TYPES.foo]: { route: "foo", select: (s: RootState) => s.foo, }, [SOME_TYPES.fooBar]: { route: "bar", select: (s: RootState) => s.fooBar, }, [SOME_TYPES.bar]: { route: "gift", select: (s: RootState) => s.bar, }, } satisfies Record< SOME_TYPES, { route: string; select: (s: RootState) => any; } >;

This is how I create the RootReducer (I am using RTK):

const rootReducer = combineReducers({ [SOME_TYPES.bar]: barSlice, [SOME_TYPES.foo]: fooSlice, [SOME_TYPES.fooBar]: fooBarSlice, });

Now, I want to dynamically access the slice, depending on the path of the URL:

const randomType = (): SOME_TYPES | null => { const enumValues = [SOME_TYPES.foo, SOME_TYPES.bar, SOME_TYPES.fooBar]; const randomIndex = Math.floor(Math.random() * (enumValues.length + 1)); return randomIndex === enumValues.length ? null : enumValues[randomIndex]; };

randomType returns either SOME_TYPES or null.

The problem is here:

const someType = randomType(); const slice = useAppSelector(state => someType ? myRegistry[someType].select(state) : undefined)

The compiler tells me that slice is always barState.

Why is it not also fooBarState or fooState?

Here is a Sandbox https://codesandbox.io/p/sandbox/purple-meadow-6l9wk5

Read Entire Article