14

Given the following:

interface MyInterface {
  type: string;
}

let arr: object[] = [ {type: 'asdf'}, {type: 'qwerty'}]

// Alphabetical sort
arr.sort((a: MyInterface, b: MyInterface) => {
      if (a.type < b.type) return -1;
      if (a.type > b.type) return 1;
      return 0;
    });

Can someone help decipher the TS error:

// TypeScript Error
[ts]
Argument of type '(a: MyInterface, b: MyInterface) => 0 | 1 | -1' is not assignable to parameter of type '(a: object, b: object) => number'.
  Types of parameters 'a' and 'a' are incompatible.
    Type '{}' is missing the following properties from type 'MyInterface': type [2345]
skube
  • 5,867
  • 9
  • 53
  • 77
  • 1
    Can't reproduce with the posted code. `let arr:object[]` is the only way I can reproduce the error .. – Titian Cernicova-Dragomir Jan 21 '19 at 21:36
  • 1
    cant reproduce the error. [see this](http://www.typescriptlang.org/play/#src=interface%20MyInterface%20%7B%0D%0A%20%20type%3A%20string%3B%0D%0A%7D%0D%0A%0D%0Alet%20arr%20%3D%20%5B%20%7Btype%3A%20'zasdf'%7D%2C%20%7Btype%3A%20'qwerty'%7D%5D%0D%0A%0D%0A%2F%2F%20Alphabetical%20sort%0D%0Aarr.sort((a%3A%20MyInterface%2C%20b%3A%20MyInterface)%20%3D%3E%20%7B%0D%0A%20%20%20%20%20%20if%20(a.type%20%3C%20b.type)%20return%20-1%3B%0D%0A%20%20%20%20%20%20if%20(a.type%20%3E%20b.type)%20return%201%3B%0D%0A%20%20%20%20%20%20return%200%3B%0D%0A%20%20%20%20%7D)%3B) – Derviş Kayımbaşıoğlu Jan 21 '19 at 21:37
  • Isn't `object[]` the equivalent to the array of objects shown? In any case, I've updated the original post to include the type for `arr` – skube Jan 21 '19 at 21:38
  • 1
    No it is not. If you leave out the type, TS infers it, so the type of `arr` will be `{type: string;}[]` and you don't get the error. If you set it to `object` the you get the error since the argument to the callback are not compatible with `object`. – Titian Cernicova-Dragomir Jan 21 '19 at 21:48
  • So essentially, the correct answer is to `let arr: [MyInterface]` ? – skube Jan 21 '19 at 21:52
  • 1
    Be careful : it's `let arr: MyInterface[]`. Otherwise, it's a tuple in Typescript – pom421 Sep 21 '19 at 22:51

2 Answers2

18

Here is a simplified example to reproduce the error:

interface MyInterface {
  type: string;
}
let arr:object[] = []
// Error: "object" is not compatible with MyInterface 
arr.sort((a: MyInterface, b: MyInterface) => {});

The reason its an error is because object cannot be assigned to something that is of type MyInterface:

interface MyInterface {
  type: string;
}
declare let foo: object;
declare let bar: MyInterface;
// ERROR: object not assignable to MyInterface
bar = foo; 

And the reason this is an error is because object is synonymous with {}. {} does not have the type property and therefore incompatible with MyInterface.

Fix

Perhaps you meant to use any (instead of object). any is compatible with everything.

Better fix

Use the exact type i.e. MyInterface

interface MyInterface {
  type: string;
}
let arr:MyInterface[] = []; // Add correct annotation 
arr.sort((a: MyInterface, b: MyInterface) => {});
basarat
  • 261,912
  • 58
  • 460
  • 511
0

If an object is already of a defined type it may cause this error.

// does not work
var user = aws.results.Item;
user = getUserType(user);
doSomething(user);

// works
var user = aws.results.Item;
var userTyped = getUserType(user);
doSomething(userTyped);

// typed user parameter
function doSomething(user: User) {}

Instead of reusing an existing reference create a new one.

1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231