Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: why check of type object[] fails if array contains an empty object variable?

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.

like image 221
klues Avatar asked Dec 07 '25 16:12

klues


2 Answers

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.

like image 109
Ricky Mo Avatar answered Dec 09 '25 16:12

Ricky Mo


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

like image 44
Behemoth Avatar answered Dec 09 '25 17:12

Behemoth



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!