I want to manipulate an object with a function that parses all given keys to a number. In addition, the function should create the correct type for the object.
This is what I have until now:
type ReplaceStringWithNumber<T> = T extends string ? number : T
type ReplaceStringsWithNumbers<T extends Record<PropertyKey, unknown>, K extends keyof T> = {
[P in keyof T]: P extends K ? ReplaceStringWithNumber<T[P]> : T[P]
}
export function parseIntIfSet<T extends Record<string, unknown>, K extends keyof T>(
object: T | ReplaceStringsWithNumbers<T, K>,
key: K
): asserts object is ReplaceStringsWithNumbers<T, K> {
if (object[key]) {
object[key] = Number(object[key]) as T[K]
}
}
It looks good for now but when I test the function:
const p = {id: '1'}
parseIntIfSet(p, 'id')
// `p.id` is of type `never`, because `p` is of type `{id: string} & {id: number}`
Does anyone know how to solve this? A solution which works is to return a new object with the manipulated type, but this is not exactly what I want.
I am also not sure, why I need to use T | ReplaceStringsWithNumbers<T, K> in the parameters as I get an error if I just use T.