Why the check for type object[] fails, if the array contains a variable containing an empty object like this:
let emptyObject = {};
let objectArray : object[] = [emptyObject, true, 1]; // no compile error, but should throw error
Playground link
This doesn't show any error or warning, but it should, since true and 1 shouldn't be possible in an array with type object[].
If I use an empty object literal {} directly or a non-empty object, everything works as expected:
let objectArray2 : object[] = [{}, true, 1]; // as excpected: type 'boolean' is not assignable to 'object'
let nonEmptyObject = {a: 1};
let objectArray3 : object[] = [nonEmptyObject, true, 1]; // as expected: type 'boolean' is not assignable to 'object'
Playground link
Is this a bug of TypeScript, or am I missing something?
I'm using TypeScript version 5.4.5.
A quick Google search to this article
The empty object type - {} - doesn't behave how you expect in TypeScript.
Instead of representing an empty object, it represents any value except null and undefined.
Which means type {} is effectively any minus undefined and null, you can expect it behave similar to any when null and undefined aren't in the equation, i.e. opt-out type checking.
When you have some elements in an array opted out type checking, the whole array is opted out.
let emptyObject = {}; effectively declared emptyObject as type {}, while the empty object inside [{}, true, 1] has not yet asserted a type, so it get a chance follow the type of the array.
If you write [{} as {}, true, 1];, the error will get removed, same effect as [{} as any, true, 1];
In reverse, if you write let emptyObject : object = {};, this narrow the type of the empty object from type {} to type object, and the error appear.
This is due to TypeScript's Best Common Type inference of the array.
When you say
let emptyObject = {};
let objectArray: object[] = [emptyObject, true, 1];
the array is actually inferred with type {}[]. And {}[] is assignable to object[]. So there's no compiler error.
You can change the type inference by using a const-assertion like so:
let emptyObject = {};
let objectArray: object[] = [emptyObject, true, 1] as const;
// ~~~~ ~
// ... is not assignable to type 'object'.
That way the array will be inferred as a tuple with type readonly [{}, true, 1] which is clearly not assignable to object[].
TypeScript Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With