Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Typing Hooks and the Store in React Native with TypeScript

Typing Hooks and the Store

~15 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

cartStore.ts from chapter 12 is already typed – now it's the turn of the Redux Toolkit favorites store from chapter 3, EXACTLY like "React for Professionals" chapter 42, plus a React Native-specific detail: Reanimated's useSharedValue.

favoritesSlice.js to favoritesSlice.ts

store/favoritesSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';

interface FavoritesState {
  skus: string[];
}

const initialState: FavoritesState = { skus: [] };

const favoritesSlice = createSlice({
  name: 'favorites',
  initialState,
  reducers: {
    toggleFavorite(state, action: PayloadAction<string>) {
      const sku = action.payload;
      if (state.skus.includes(sku)) {
        state.skus = state.skus.filter((s) => s !== sku);
      } else {
        state.skus.push(sku);
      }
    },
  },
});

export const { toggleFavorite } = favoritesSlice.actions;
export default favoritesSlice.reducer;

store/index.js to index.ts

store/index.ts
import { configureStore } from '@reduxjs/toolkit';
import favoritesReducer from './favoritesSlice';

export const store = configureStore({
  reducer: {
    favorites: favoritesReducer,
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

Creating store/hooks.ts: typed useSelector/useDispatch

Identical pattern to "React for Professionals" chapter 42:

store/hooks.ts
import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux';
import type { RootState, AppDispatch } from './index';

export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

From now on, use useAppSelector/useAppDispatch instead of the "bare" hooks from react-redux – the selector parameter automatically gets the correct RootState type:

// In FavoritesScreen.tsx / ProductListScreen.tsx:
import { useAppSelector, useAppDispatch } from '../store/hooks';

const favoriteSkus = useAppSelector((state) => state.favorites.skus);
const dispatch = useAppDispatch();

Reanimated hooks: typed automatically, with one exception

useSharedValue, useAnimatedStyle, and withSpring from chapters 9/13 are already FULLY typed, without us doing anything – useSharedValue(1) automatically infers SharedValue<number>, EXACTLY like useState(1) automatically infers number (see "React for Professionals" chapter 42). ONE spot still needs attention: runOnJS from the Gesture Handler chapter.

import { runOnJS } from 'react-native-reanimated';

function onRemove(sku: string): void {
  // ...
}

// TypeScript checks that runOnJS(onRemove)'s arguments match onRemove's signature:
runOnJS(onRemove)(item.sku); // sku: string - matches (sku: string) => void

Achtung: runOnJS is GENERIC over the function signature of the function passed to it – if you accidentally pass a number instead of a string (runOnJS(onRemove)(42)), TypeScript reports the error IMMEDIATELY. This is especially valuable with runOnJS, since a runtime error INSIDE a worklet (on the UI thread) is often harder to debug than a regular JS-thread error.

Typing Gesture.Pan() events

import { Gesture } from 'react-native-gesture-handler';
import { GestureUpdateEvent, PanGestureHandlerEventPayload } from 'react-native-gesture-handler';

const panGesture = Gesture.Pan().onUpdate(
  (event: GestureUpdateEvent<PanGestureHandlerEventPayload>) => {
    translateX.value = Math.min(0, event.translationX);
  }
);

In practice, TypeScript usually infers the event type inside .onUpdate(...) AUTOMATICALLY and correctly, without the explicit annotation – it's shown here for CLARITY, to make explicit which type actually sits behind it, for the case where you extract event into a separate, named function (there, the explicit annotation becomes MANDATORY).

Tipp: Rule of thumb for third-party libraries: before writing a type by hand, check whether the library already EXPORTS it (like GestureUpdateEvent, PanGestureHandlerEventPayload here) – modern RN libraries like Reanimated and Gesture Handler are themselves written in TypeScript and ship precise, author-maintained types that are more reliable than hand-written approximations.