When I have to iterate on the keys of mappedTypes, I always struggle to make Typescript narrow the type of the value associated with the key I am iterating on and always finish with a ts-ignore
...
A code sample demonstrating the issue worths a 1000 words :) Here it is !
type Person = {
firstName?: string
lastName?: string
age?: number
}
type Update<T> = {
before: T,
after: T,
}
type Updates = { [Key in keyof Person]: Update<Person[Key]> }
/**
* Dummy transformers for illustration purposes
*/
const transformers : {[Key in keyof Person]: (value: Person[Key]) => Person[Key]} = {
firstName: value => value?.toUpperCase(),
lastName: value => value?.toUpperCase(),
age: value => typeof value === 'undefined'? 0 : value + 2
}
/**
* Input: {firstName: 'david', age: 23}
* Output: {firstName: {before: 'david', after: 'David'}, age: {before: 22, after: 24}}
* @param person
*/
function enrichPerson (person: Person): Updates {
return Object.keys(person).reduce(
(previousUpdates, key) => {
const typedKey = key as keyof Person
const result = { ...previousUpdates }
result[typedKey] = {
before: person[typedKey], // <--- Typing problem Here
after: transformers[typedKey](person[typedKey]), // <--- Typing problem Here
}
return result
},
{} as Updates
)
}
export {}
What can I do to narrow the type of the value ? If it is not possible, what pattern would you use in this case ?
Thanks a lot for your help ! This problem is haunting me !