Home > Software design >  Is it possible to infer generic `T | undefined` as `Partial<T>` without casting?
Is it possible to infer generic `T | undefined` as `Partial<T>` without casting?

Time:12-03

I have this function that applies default values to an object if it's undefined. For properties that don't have a default value provided, I want to keep original type with | undefined.

What I have right now works, but would it be possible to prevent type casting as Partial<T>?

const setDefaults = <T extends object, K extends keyof T>(
  data: T | undefined,
  defaults: Pick<T, K>,
) => {
  return { ...defaults, ...(data as Partial<T>) }
}

type MyData = {
  id: number,
  roles: Array<string>,
}

let data: MyData | undefined

const { id, roles } = setDefaults(data, { roles: [] })

console.log(id) // number | undefined
console.log(roles) // Array<string>

CodePudding user response:

So, data really is not Partial<T>; it's T | undefined. It's defaults that is Partial<T>. My suggested fix is to intersect the type of defaults with Partial<T> so that the compiler understands that any properties not explicitly mentioned in the argument are of type undefined (instead of just unknown):

const setDefaults = <T extends object, K extends keyof T>(
  data: T | undefined,
  defaults: Pick<T, K> & Partial<T>, // <-- here
) => {
  return { ...defaults, ...data }
}

This has the same Pick<T, K> & Partial<T> return type as before, so everything works as expected:

const { id, roles } = setDefaults(data, { roles: [] })  
id; // number | undefined
roles; // Array<string>

Playground link to code

  • Related