Reputation: 75
I am trying to create a custom sort function for an array of objects of varying types. I would like the function to be generic enough to work for many types that contain atleast one string property.
interface Record {
id: string
name: string
}
const sortStr = (field: keyof Record, reverse: boolean) => {
return (a: Record, b: Record) =>
a[field] !== "" && b[field] !== ""
? (reverse ? -1 : 1) *
a[field].localeCompare(b[field], undefined, { sensitivity: "base" })
: a[field] !== "" && b[field] === ""
? -1
: a[field] === "" && b[field] !== ""
? 1
: 0
}
Can I declare the type of the 'field' param to be the keyof any object that is of type string?
For example, the function above won't work if Record has a number property because localCompare is a string function.
interface Record {
id: string
name: string
user: number
}
Solution
This worked for me, edited from caTS' answer:
type KeysOfType<O, T> = {
[K in keyof O]: O[K] extends T ? K : never
}[keyof O]
const sortStr = (field: KeysOfType<any, string>, reverse: boolean) => {
return (a: any, b: any) => ...
}
Upvotes: 2
Views: 60
Reputation: 26307
You could define a type to get the keys that have a specific type like this:
type KeysOfType<O, T> = {
[K in keyof O]: O[K] extends T ? K : never
}[keyof O];
and then you can use it in your function:
const sortStr = (field: KeysOfType<MyRecord, string>, reverse: boolean) => {
Note that I renamed Record
to MyRecord
since Record
is already a built-in type.
Upvotes: 2