I'm building a generic function that will allow to update nested object properties (ideally based on inferred type - but this is nice to have rather than requirement).
On the top of that please keep in mind - I am not a Typescript expert so I would be glad for pointing out any mistakes.
So here is the example state + types for it:
type DataType = {
knownKeyName1: {
knownNestedKeyName1: string
knownNestedKeyName2: string
knownNestedKeyName3: string
knownNestedKeyName4: string
}
knownKeyName2: {
knownNestedKeyName1: string
knownNestedKeyName2: string
knownNestedKeyName3: string
}
}
type SomeState = {
data: DataType
}
const someState: SomeState = {
data: {
knownKeyName1: {
knownNestedKeyName1: 'value',
knownNestedKeyName2: 'value',
knownNestedKeyName3: 'value',
knownNestedKeyName4: 'value'
},
knownKeyName2: {
knownNestedKeyName1: 'value',
knownNestedKeyName2: 'value',
knownNestedKeyName3: 'value'
}
}
}
And below is the function that I've already tried to build with Typescript's generics:
const setStateValue = <
State extends { data: unknown }, // I want this to infer type from `someState` variable whenever I pass it to this function
Prop extends [keyof State['data']],
VarName extends keyof State['data'][Prop] // Type 'Prop' cannot be used to index type 'State["data"]'.ts(2536)
>(
state: State,
prop: Prop,
varName: VarName,
newValue: string
): void => {
state.data[prop][varName] = newValue
// Example usage should results with:
// state.data[knownKeyName1][knownNestedKeyName3] = 'someNewValue'
}
JavaScript equivalent:
const setStateValue = (state, prop, varName, newValue) => {
state.data[prop][varName] = newValue // Object property reassignment is done on purpose because we want to update the state in reducer with `immer`
}
Any ideas? Additionally, if that's not possible then it would be nice to at least have something like this:
const setStateValue = <
State extends { data: DataType },
Prop extends keyof DataType,
VarName extends keyof DataType[Prop]
>(
state: State,
prop: Prop,
varName: VarName,
newValue: string
): void => {
state.data[prop][varName] = newValue // but then this error pops out:
// Type 'string' is not assignable to type 'DataType[Prop][VarName]'.ts(2322)
}
Thanks in advance!
P.S Adding #redux-toolkit tag to give some usage context, as I want to use this setStateValue function inside generic reducer (so the state can be mutated with immer).