0

I am new in TypeScript. I might be asking a rookie question. I have the following array of objects. I would like to sort it either by age or name. This question was asked before. I tried following after reading this answer. And this. I couldn't compile it in TypeScript.

    sortData2() {
  const testData: object[] =  [
    {
      name: 'name 1',
      age: 20,
      sex: 'M',
      height: 7.5
    },
    {
      name: 'name 1',
      age: 10,
      sex: 'M',
      height: 6.5
    },
    {
      name: 'name 3',
      age: 30,
      sex: 'F',
      height: 4.5
    }
  ];

  testData.sort( (a, b) => {
      return compare(a, b);
  });

  
  function compare(a: number | string | object, b: number | string | object) {
    // compiler error Property 'age' does not exist on type 'string | number | object'.
    return (a.age < b.age ? -1 : 1);
  }
  console.log(testData);
}

How can I sort it? Thanks in advance!

8
  • 1
    Is there a reason you're declaring compare as a function instead of defining it inline ? You should also probably remove the object[] type: typescript will infer something better Commented Sep 27, 2020 at 13:37
  • 3
    a and b wouldn't be number | string | object only object. And even then, you are better off defining an interface for your objects, so you can more accurately typecheck. Commented Sep 27, 2020 at 13:37
  • Actually, I got an array of objects from another function call. I can’t change that 3rd party api call. So I can’t define any kind of interface of my own. Commented Sep 27, 2020 at 13:41
  • You cannot write interface Person {name: string, age: number, sex: 'F' | 'M, height: number }? Commented Sep 27, 2020 at 13:45
  • I tried to simulate my real code and issue by this simple person like interface. My real code is far more complex than this simple interface. Commented Sep 27, 2020 at 13:58

1 Answer 1

2

In your compare function, you are saying that a and b can be an object, string, or number; but then you are checking a.age, which doesn't make sense unless a and b are objects which have the property age. So why are you accepting so many possible types here?

Replace this:

function compare(a: number | string | object, b: number | string | object) {
    return (a.age < b.age ? -1 : 1);
}

With this:

function compareAge(a: {age: number}, b: {age: number}): number {
    return (a.age < b.age ? -1 : 1);
}

Or better yet, this, which better handles the case where a.age and b.age are equal. An array.sort compare function should return a number less than 0 if a is less than b, greater than 0 if a is greater than b, or 0 if they are equal. The actually value of the number doesn't matter -- just the sign. So you can map to -1 or 1, but it is unnecessary. A simple subtraction allows for returning positive, negative, and 0.

function compareAge(a: {age: number}, b: {age: number}): number {
    return a.age - b.age;
}

You will still get an error when calling testData.sort( compareAge ); because you have declared a very vague type with testData: object[]. You can either remove this typing entirely and Typescript will infer the proper type, or you can declare it as a more specific type, like testData: Person[]. You will be able to sort with compareAge as long as the elements of testData (or any other array) extend {age: number}.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.