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.