I'm working on the following type definitions:
type NumericKeys<T> = {
[K in keyof T]: T[K] extends number ? K : never
}[keyof T]
type Update<T extends Record<string, any>> = {
$set?: {
[K in keyof T]?: T[K]
},
$inc?: Partial<Pick<T, NumericKeys<T>>>
}
Things are pretty close to the way that I want them except that in the case of both $set and $inc, these types allow a user to provide an explicit undefined value to any of the nested properties. Ideally all the properties in both objects would be optional, but if the user provides them they must match the type of the corresponding property from the original object.
type Item = {
name: string;
description: string;
count: number
}
const example: Update<Item> = {
$set: {
// Ideally this would throw a type error because it should be type string
name: undefined
},
$inc: {
// Ideally this would throw a type error because it should be type number
count: undefined
}
}