Home > OS >  Extract Typescript Object Properites from Non Properties
Extract Typescript Object Properites from Non Properties

Time:07-07

I am trying to generate two objects from one larger object to see if the property is listed within the given Generic type.

Meaning if I give something like:

{
   name: "John",
   enabled: false,
   lastName: "Doe",
   age: 33
}

and the type is:

type User = {
   name: string;
   lastName: string;
   age: number 
}

Result of function would be format of (Non In Type, InType)

[
   {
      enabled: false
   }, 
   {
      name: "John",
      lastName: "Doe",
      age: 33
   }
]

Here is what I have tried so far:

type GenericType<T> = Partial<T> & {
[record: string]: unknown
}

// Values are known properites of T
const sortProperties = <T>(values: string[], orginalObject: GenericType<T>){

   const validPropertieis: Partial<T> = {};
   const inValidProperties: Record<string, unknown> = {};

   Object.keys(orginalObject).forEach((key) => {
      if(values.includes(key){
         // No index signature with parameter type 'string' was found on type Partial<T>
         validPropertieis[key] = values[key];
      }
      else {
          inValidProperties[key] = values[key];
      }

   return [inValidProperties, validProperties];

}

CodePudding user response:

EDIT:

Here's a solution:

// The valid properties we want
const arr = ['hi', 'test', 'abc'] as const;

const obj = {
    hi: 'foo',
    test: 420,
    abc: 'bar',
    // Oops, extra property
    oops: 123,
};

const validateProperties = <A extends ReadonlyArray<string>, T extends Record<string, unknown>>(values: A, object: T) => {
    return Object.keys(object).reduce((acc, key) => {
        if (!values.includes(key)) acc[0] = { ...acc[0], [key]: object[key] };
        else acc[1] = { ...acc[1], [key]: object[key] };

        return acc;
    }, [] as unknown as [Omit<T, A[number]>, Pick<T, A[number]>]);
};

const test = validateProperties(arr, obj);

Your IDE will autofill the properties when trying to access them. The only thing to note is that the string[] must be either const or a tuple of strings so that TypeScript can infer the literal types.

CodePudding user response:

Based on the description you gave I would suggest a solution like this:

type Expand<T> = T extends infer U ? { [K in keyof U]: U[K] } : never
type SortReturnType<K extends string, T> = [Expand<Omit<T, K>>, Expand<Pick<T, K & keyof T>>]

const sortProperties = <
  K extends string, 
  T
>(v1: K[], v2: T): Expand<SortReturnType<K, T>> => {

   const validProperties: Partial<T> = {};
   const inValidProperties: Partial<T> = {};

   Object.keys(v2).forEach((key) => {
      if (v1.includes(key as any)) {
        validProperties[key as keyof T] = v2[key as keyof T]
      } else {
        inValidProperties[key as keyof T] = v2[key as keyof T];
      }
   })

   return [inValidProperties, validProperties] as SortReturnType<K, T>;
}

Let's see if it works.

const result = sortProperties(["name", "lastName", "age"], {
  name: "abc",
  lastName: "abc",
  enabled: true,
  age: 0
})
// const result: [{
//     enabled: boolean;
// }, {
//     name: string;
//     lastName: string;
//     age: number;
// }]

Look's fine to me. Let me know if this fits your requirements.

Playground

CodePudding user response:

Another try:

type User = {
  name: string;
  lastName: string;
  age: number;
};

const testUser = {
    name: "John",
    enabled: false,
    lastName: "Doe",
    age: 33,
  },
  userTypeKeys = ["name", "lastName", "age"];

function sortProperties<T>(values: string[], object: T) {
  const validProperties: Partial<T> = {},
    invalidProperties: Record<string, unknown> = {};

  Object.keys(object).forEach((key: string) => {
    if (values.includes(key)) {
      validProperties[key as keyof T] = object[key as keyof T];
    } else {
      invalidProperties[key] = object[key as keyof T];
    }
  });

  return [invalidProperties, validProperties];
}

const properties = sortProperties(userTypeKeys, testUser);

// logs [ { enabled: false }, { name: 'John', lastName: 'Doe', age: 33 } ]
console.log(properties);
  • Related