What's the difference between object
and {}
in TypeScript?
— by Gabriel Vergnaud · Sep 10, 2023
I used to think that object
was an alias for the {}
"empty object" type in TypeScript, but I was wrong! These two types represent different sets of values, and if you want to write accurate type definitions for your functions and classes, it's important to know which one to choose.
Let's see how they differ!
The {}
empty object type
The empty object {}
type is one of the largest sets of values TypeScript has. All types with properties or methods are assignable to it, including primitive types, like number
, string
and boolean
!
It means that a function taking a {}
will happily accept most values:
Only two types aren't assignable to the empty object type: null
and undefined
.
That's the only difference between {}
and the unknown
type by the way. unknown
includes every single JavaScript value, including null
and undefined
:
The object
type
Now let's look at the object
type. Unlike {}
, object
does not include primitive types!
That's what makes it different from the {}
type. Here is what happens if you try assigning a primitive type like a string
or a number
to object
:
But what about functions and arrays?
They are assignable to the object
type too. It's really only primitive types that aren't.
Which one should you use?
When writing a generic function, you usually want to use the object
type. For example, consider the following merge
function:
const merge = <
A extends {},
B extends {}
>(a: A, b: B): A & B => ({
...a,
...b,
});
It won't throw if you give it a string or a number, but the result will look very weird:
const result = merge(42, "what?"); // type-checks
// => {0: 'w', 1: 'h', 2: 'a', 3: 't', 4: '?'}
Is this really what you expected? Probably not.
If you constrain your type parameters with the object
type instead, passing numbers or strings will simply not type-check:
Nobody will ever mistakenly pass a string to your merge
function again! 🎉🎉
Summary 📚
Here are the main takeaways from this article:
- Types are sets of values.
{}
includes all primitive types.object
does not.
The behavior of the {}
type isn't extremely intuitive, so my advice is to use the object
type unless you really know what you are doing!
If you liked this article, chances are you'll like Type-Level Typescript. It's an advanced TypeScript course that will give you a solid understanding of the type system's fundamentals and guide you through its most advanced features. Enroll Now!
Subscribe to the newsletter!
Receive all new chapters and articles from Type-Level TypeScript directly in your inbox!