Home > Net >  How can I replace all types of a nested object recursively based on some conditions?
How can I replace all types of a nested object recursively based on some conditions?

Time:12-21

In the Further Exploration example on TypeScript website they show us a way to replace the type of a property with a different type based on some conditions.

How can we do the same but in a recursive way? i.e. not only map the first level properties, but any nested property that passes the check.

The example:

type ExtractPII<Type> = {
  [Property in keyof Type]: Type[Property] extends { pii: true } ? true : false;
};

type DBFields = {
  id: { format: "incrementing" };
  name: { type: string; pii: true };
};

type ObjectsNeedingGDPRDeletion = ExtractPII<DBFields>;
// type ObjectsNeedingGDPRDeletion = { id: false; name: true; }

What I need:

type DBFields = {
  id: { format: "incrementing", foo: { type: string; pii: true } };
  name: { type: string; pii: true };
};

type ObjectsNeedingGDPRDeletion = ExtractPII<DBFields>; 
// type ObjectsNeedingGDPRDeletion = { id: { format: string; foo: true }; name: true; }

CodePudding user response:

In the false case, you just need to execute another check to see if the type is an object, and then call ExtractPii on that property.

type ExtractPII<T> = {
  [P in keyof T]: T[P] extends { pii: true } 
    ? true 
    : T[P] extends object 
      ? ExtractPII<T[P]> 
      : T[P];
};

This will results in:

type DBFields = {
  id: { format: "incrementing", foo: { type: string; pii: true } };
  name: { type: string; pii: true };
};

type ObjectsNeedingGDPRDeletion = ExtractPII<DBFields>;

const a: ObjectsNeedingGDPRDeletion = {
    name: true,
    id: {
        foo: true,
        format: "incrementing"
    }
}

If you want in the false case the value false, then just replace T[P] with false:

type ExtractPII<T> = {
  [P in keyof T]: T[P] extends { pii: true } 
    ? true 
    : T[P] extends object 
      ? ExtractPII<T[P]> 
      : false;
};
  • Related