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
};