2

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) => ...
}

1 Answer 1

2

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.

Playground

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.