How to Type Empty Objects in TypeScript
A common mistake I see when people are writing their types for empty objects is this:
// ❌ Don't do this:
type EmptyObject = {};
Why?
The assignment of {} just means any non-nullish value.
This means we can assign everything except null to our type.
As an example:
type EmptyObject = {};
// ✅ Passes the Type check:
const test1: EmptyObject = "This is a test";
// ✅ Passes the Type check:
const test2: EmptyObject = {};
// ✅ Passes the Type check:
const test3: EmptyObject = {
test: "Yes, I work too...",
};
// ❌ Fails the Type check: Type 'null' is not assignable to type 'EmptyObject'
const test4: EmptyObject = null;
How to enforce an empty object?
To declare an object as an object with no properties, we have to be more explicit:
type EmptyObject = Record<PropertyKey, never>;
Now if we tried to assign a value we will start seeing type errors.
type EmptyObject = Record<PropertyKey, never>;
// ❌ Fails the Type check: Type 'string' is not assignable to type 'EmptyObject'.
const test1: EmptyObject = "This is a test";
// ✅ Passes the Type check
const test2: EmptyObject = {};
// ❌ Fails the Type check: Type 'string' is not assignable to type 'never'.
const test3: EmptyObject = {
test: "Yes, I work too...",
};
// ❌ Fails the Type check: Type 'null' is not assignable to type 'EmptyObject'
const test4: EmptyObject = null;
How does this work?
The Record utility lets us define the accepted keys and values.
Its structure is:
Record<Keys, Type>
The PropertyKey is an alias that says the key can be a string, a symbol, or a number (or a normal property key).
Then the never says the value will never occur, meaning if we try to assign a value to a key, we will get a type error.
Follow me on Twitter or connect on LinkedIn.
🚨 Want to make friends and learn from peers? You can join our free web developer community here. 🎉
