Have you ever used the {}
type definition in TypeScript?
It represents the type "empty object", which is an object with zero own properties.
You could also use the type definition {id: 1}
which is only satisfied with the object {id: 1}
.
Of course we can use this behaviour if needed. But it may lead to unexpected TypeScript errors.
Consider the following TypeScript code:
interface User {
id: number
name: string
}
function getUser(id: number): User | {} {
if (id === 1) {
return {
id: 1,
name: 'Dagobert D.'
}
}
return {}
}
const user = getUser(1)
console.log(user.name?.replace('.', ''))
It looks fine and will work. When we call getUser(1)
we get the full object with the properties id
and name
.
Running the code will log Dagobert D
.
And when we call getUser(2)
we receive an empty object which will lead to user.name?.replace('.', '')
being evaluated as undefined
.
The code will compile.
But there's a TypeScript error:
Property 'name' does not exist on type '{} | User'.
Property 'name' does not exist on type '{}'.
And it's correct! There is no property name
on type {}
.
So, how do we fix this?
There are two fixes:
User | Partial<User>
instead of User | {}
. You could even shorten this to Partial<User>
. Use this solution if you are sure a partial object is necessary here.User
or undefined
: Type User | undefined
. This is usually the better solution (i.e. the "TypeScript way").Here's the working code without errors:
interface User {
id: number
name: string
}
function getUser(id: number): User | undefined {
if (id === 1) {
return {
id: 1,
name: 'Dagobert D.'
}
}
return undefined
}
const user = getUser(1)
console.log(user?.name.replace('.', ''))
There are few scenarios where returning an empty object is better than returning nothing. Consider your case and refactor appropriately.