I have a uniqBy
function defined thus:
export function uniqBy<T>(a: T[], key: any): T[] {
const seen = {};
return a.filter(function (item) {
if (item) {
const k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
} else {
return false;
}
});
}
This strongly types my return value based on the input array, but I would also like key
parameter to be strongly typed so that I get compile-time errors if I try to pass in a property that doesn't exist on T
.
example of current usage:
uniqArray = uniqBy(this._checkups, x => x.CatDescription);
_checkups
being an array of the following:
export interface Checkup {
id: string;
CatDescription: string;
ProcessTitle: string;
MsgProcessID: number;
MsgDate: string;
MsgStatus: number;
MsgText: string;
MsgAction: string;
MsgEntityID: string;
MsgEntity: string;
}
I would like it if trying to do the following:
uniqArray = uniqBy(this._checkups, x => x.NonExistantProperty);
gave me a compile-time error (and IntelliSense on the property completion). How would I define key
in the parameters in order to do this?
This would return an array of items with only unique values of CatDescription
(taking the first object with a CatDescription
in the event of duplicates).
I don't know what this is called, it's not a Predicate<T>
as that is for filtering and returns a boolean.
Seems like as second parameter you pass callback but you don't have a type for it so you an just give it a type (val: T) => T[keyof T]
export function uniqBy<T>(a: T[], key: (val: T) => T[keyof T]): T[] {
const seen = {};
return a.filter(function (item) {
if (item) {
const k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
} else {
return false;
}
});
}
Then by adding non existent key it will give you an error
uniqArray = uniqBy<Checkup>(this._checkups, x => x.NonExistantProperty);