Ayyappa
Ayyappa

Reputation: 1984

Declare nested object leaf key values as undefined in typescript

Consider a nested object like below

class Person {
    name: string = 'name';
    address: {street: string, pincode: string} = {street: 'street', pincode: '44555'};
}

There is a utility function(undefinedAllLeadNodes) which undefines all leaf nodes. So passing a new Person() creates below

person.name = undefined
person.address.street = undefined;
person.address.pincode = undefined;

If i declare as below

export function undefineAllLeafProperties<
    T extends object
>(obj : T) :  {[key: string] : any} {
    ...undefine all leaf nodes here
}

It shows compilation error for person.address.street and it sounds fine for {[key: string] : any} return type declaration.

But What can be the proper return type for the utility function(undefinedAllLeadNodes) so that i can access it like below without any errors

person.address.street = 'update only street';

Upvotes: 0

Views: 149

Answers (1)

aleksxor
aleksxor

Reputation: 8340

You may define such a type like this:

type Undefine<T extends object> = {
  [K in keyof T]: T[K] extends object ? Undefine<T[K]> : T[K] | undefined
}

playground link

Here we're using mapped types to iterate over all keys (using keyof operator) of the provided T object and conditional type to check whether the value of T[K] (using lookup type) is an object again. And when it is we recursivly iterate over the T[K] keys. Otherwise (when T[K] is not an object) we just change it's type to allow undefined value along the main type of T[K].

Keep in mind that inside the undefineAllLeafProperties function code you may have to type assert return values . Because typescript generally cannot infer the exact shape of the conditional type when it depends on unspecified generic type parameter.

Upvotes: 1

Related Questions