I have a complicated type with many nested properties. I want type narrowing. This seems to work for basic primitives, but when an object is involved, TS cannot seem to narrow the properties using the same principles.
type Test = {
property: string | null
}
const propIsNotNull = (data: Test): boolean => {
return (data.property !== null)
}
const testData: Test = {
property: 'nonull'
}
if (propIsNotNull(testData)) {
console.log(testData.property.toUpperCase())
// ~~~~~~~~~~~~~~~~~
// 'testData.property' is possibly 'null'.(18047)
}
I can of course change it to the following, but it makes the code harder to read
if (testData.property !== null) {
console.log(testData.property.toUpperCase())
}
I don't really want to make a new type just so I can use a type guard. I feel like I am missing something fundamentally simple.
CodePudding user response:
A function without a type predicate will never have any narrowing capabilities. You also don't need a new type just to make a type predicate. There are multiple ways to reuse the type and just modify the part that you are checking.
One possible way would look like this:
const propIsNotNull = (data: Test): data is Test & {
property: Exclude<Test["property"], null>
} => {
return (data.property !== null)
}
The type predicate signals to the caller that data
is of type Test
and that the property property
is not null
if the condition is true
.