Dynamic types with use context selector

460 Views Asked by At

I am using use-context-selector in my react/typescript application and I am struggling with having some dynamic types.

Here is a context that I have:

type AbilityContextType = {
  attack: () => number;
  defend: () => number;
  retreat: () => void;
  advance: () => void;
};

Here is a hook that I have which makes it easier for consumers of my application to consume whatever they need from the ability context.

import { createContext, useContextSelector } from 'use-context-selector';

const AbilityContext = createContext<AbilityContextType>();

const useAbilityContext = <T extends (keyof AbilityContextType)[]>(
  ...keys: T
) => useContextSelector(AbilityContext, ...keys);

And here is an example usage of said hook. The types are all working as expected.

const [attack, retreat] = useAbilityContext('attack', 'retreat');

My issue is that I am not a fan of having types inlined in my useAbilityContext function. I like to have functions and the types of functions as separated as possible for better readability. Is it possible to simplify the type of useAbilityContext by maybe moving it into its own interface/type? I've tried but it's just not working.

Preferabley, I'd like my useAbilityContext hook to look like so:

// interface UseAbilityHookType { ??? }
// type UseAbilityHookType = ???;

const useAbilityContext: UseAbilityHookType = (...keys) => useContextSelector(AbilityContext, ...keys);
1

There are 1 best solutions below

0
Alex Wayne On

You want a type that describes a generic function. Something like:

type UseAbilityHookType =
  <T extends (keyof AbilityContextType)[]>(...keys: T) => AbilityContextType[T[number]]

// usage
const useAbilityContext: UseAbilityHookType =
  (...keys) => useContextSelector(AbilityContext, ...keys);

(I am somewhat unsure of the return type, but I guess that's up to you.)