Home > OS >  How can I get object type for callback depending on enum?
How can I get object type for callback depending on enum?

Time:01-21

Imagine you have following TS code:

enum stores {
  book,
  chapter,
  verse
}

const reducer = {
  [stores.book]: { a: 'string', b: 1 },
  [stores.chapter]: { a: 'string', c: 2 },
  [stores.verse]: { a: 'string', d: false }
}

function main ({
  storeName,
  getA
}:{
  storeName: stores,
  getA: (item: typeof reducer[stores]) => void
}) {
  const item = reducer[storeName]
  getA(item)
  return
}

main({storeName: stores.verse, getA(item) {
  item.a // only can get common a attribute, but
  item.d // can't get special for stores.verse attribute
}})

What should I do to make typescript dynamically understand type of item in getA depending on storeName and reducer?

Working on my React-Redux app rn. I want to make generic component for multiple Redux slices. The API inside component consists only of common attributes, so it's fine and working, but I need to get exact type of object in slice in one of props functions

CodePudding user response:

The compiler needs to keep track of the specific member of stores which was used to call the function. This can be achieved by declaring a generic type parameter S and using it to type storeName.

The type of the value passed as storeName will be used to infer the type of S. The parameter item can be typed as typeof reducers[S].

function main<S extends stores>({
  storeName,
  getA,
}: {
  storeName: S;
  getA: (item: typeof reducer[S]) => void;
}) {
  const item = reducer[storeName];
  getA(item);
  return;
}

The type of the parameter item now depends on the enum member passed as storeName.

main({
  storeName: stores.verse,
  getA(item) {
    // ^? item: { a: string; d: boolean; }
    item.a;
    item.d;
  },
});

main({
  storeName: stores.book,
  getA(item) {
    // ^? item: { a: string; b: number; }
    item.a;
    item.b;
  },
});

Playground

  • Related