Home > Back-end >  Type narrowing object properties with a function
Type narrowing object properties with a function

Time:12-01

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.


Playground

  • Related