Reputation: 3062
Using typescript, when a function returns an object that has properties that might be null. Why does using a typeguard on these inner properties not allow typescript to infer that the inner prop must not be null after the guard?
Here's a minimum example of this. Try it
interface DatabaseResponse {
settings: string | null
}
interface MainResponse {
settings: string
}
const retrieveFromDatabase = (): DatabaseResponse => {
return {
settings: 'always a string but lets pretend it could be null sometimes'
}
}
const main = (): MainResponse | Error => {
const data = retrieveFromDatabase()
if (data.settings === null) {
throw new Error()
}
return data
}
The error for the return of the main function is
Type 'DatabaseResponse' is not assignable to type 'MainResponse | Error'.
Type 'DatabaseResponse' is not assignable to type 'MainResponse'.
Types of property 'settings' are incompatible.
Type 'string | null' is not assignable to type 'string'.
Type 'null' is not assignable to type 'string'.
Upvotes: 0
Views: 255
Reputation: 10137
That's not really a type guard. You can do this instead:
interface DatabaseResponse {
settings: string | null
}
interface MainResponse {
settings: string
}
const retrieveFromDatabase = (): DatabaseResponse => {
return {
settings: 'always a string but lets pretend it could be null sometimes'
} as DatabaseResponse
}
const main = (): MainResponse | Error => {
const data = retrieveFromDatabase()
if (!isMainResponse(data)) {
throw new Error()
}
return data
}
const isMainResponse = (data: DatabaseResponse | MainResponse): data is MainResponse {
return !!data.settings;
}
Or similarly, create a new nonNullable type with the same typeguard
type NonNullableDB = { [K in keyof DatabaseResponse]: NonNullable<DatabaseResponse[K]> }
const isMainResponse = (data: DatabaseResponse | MainResponse): data is NonNullableDB => {
return !!data.settings;
}
Upvotes: 1