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;
},
});