kamcknig
kamcknig

Reputation: 935

TypeScript: How to type a returned function's return type

Still trying to learn this typing system not sure if it's possible.

I'm working with redux and the redux toolkit, and it's mentioned that after creating the redux store, you can create a typed version of the store's dispatch and state.

Directly from their site:

import { configureStore } from '@reduxjs/toolkit'
// ...

const store = configureStore({
  reducer: {
    one: oneSlice.reducer,
    two: twoSlice.reducer
  }
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

My question is that I need to defer configuration of the store.

import { configureStore } from '@reduxjs/toolkit'
// ...

const createStore = () => configureStore({
  reducer: {
    one: oneSlice.reducer,
    two: twoSlice.reducer
  }
});

// in some other class ///
const store = createStore();

Is there anyway to get the types mentioned from the first method to actually be used within code?

edit I am looking to be able to annotate the store constant in the last example.

Upvotes: 4

Views: 2165

Answers (1)

Aluan Haddad
Aluan Haddad

Reputation: 31833

It's simply a matter of drilling down into functions return type to obtain the type of a member of the return type.

We can use TypeScript's Indexed Types to accomplish this as follows

type MemberType = MyType[memberKey];

In which we obtain the type of the member with the key memberKey of the type MyType, where memberKey is a valid key such a string or number literal or constant or a unique symbol.

In this case, to obtain the types of members getState and dispatch of the object returned by createStore when it is called, we would write

// store.ts

export const createStore = () => configureStore({
  reducer: {
    one: oneSlice.reducer,
    two: twoSlice.reducer
  }
});

// The type of the member `dispatch` of the store returned by `createStore`.
export type StoreDispatch = ReturnType<typeof createStore>["dispatch"];

// The type of the member `getState` of the store returned by `createStore`.
export type StoreGetState = ReturnType<typeof createStore>["getState"];  

Note that we can continue to drill down, for example to get the return types of these members as in

// The return type of the member `getState` of the store returned by `createStore`.
export type AppState = ReturnType<ReturnType<typeof createStore>["getState"]>;

As such syntax can become unwieldy, we can use intermediate type declarations to break it down into a more readable form

type AppStore = ReturnType<typeof createStore>;

type AppStoreGetState = AppStore["getState"];

export type AppState = ReturnType<AppStoreGetState>;

At any rate, we can now consume these types just like any others.

The following is a contrived example

// test.ts

import { createStore, AppState } from "./store";

const store = createStore();

const state: AppState = store.getState();

Upvotes: 2

Related Questions