Home > Mobile >  Partial object type which also allows arrays of the properties (preferably only primitives)
Partial object type which also allows arrays of the properties (preferably only primitives)

Time:10-22

I'm trying to create a type which is a partial of the generic type, but also allows an array as property from the corresponding type. So basically if you have the following interface:

interface DataModel {
  type: string;
  count: number;
}

The resolved type should have the following signature

{
  type?: string | string[];
  count?: number | number[];
}

and behave the following:

{ type: 'foo'} // ok
{ type: ['foo', 'bar'] } //ok
{ type: 1 } // error

I came up with this utility type, but this also allows non corresponding types to the property:

type KeyOf<T> = Extract<keyof T, string>;

type FilterProps<
  T extends object,
  U extends KeyOf<T> = KeyOf<T>
> = Partial<Record<U, T[U] | T[U][]>>;

I've made a playground which clarifies it a bit more


Preferably it would also fail on properties on the model that are not primitives, but that's not a hard requirement for me, and perhaps I can figure that one out myself.

CodePudding user response:

You can use mapped types to map each key to a different type:

interface DataModel {
  type: string;
  count: number;
}

type FilterProps<T> = {
  [K in keyof T]?: T[K] | T[K][]
}

let test1: FilterProps<DataModel> = { type: 'foo' }
let test2: FilterProps<DataModel> = { type: ['foo', 'bar'] }
let test3: FilterProps<DataModel> = { type: 1 } // Error

CodePudding user response:

To build upon @daylily's answer and to only allow primitives from the source object you can do the following:

type FilterProps<T> =  {
  [K in keyof T]?: T[K] extends (string | number | boolean)
    ? T[K] | T[K][]
    : never
};

playground

  • Related