Search code examples
typescript

Typescript check object property by existence of another property


I have a type Response

type MainTypeResponse = {
  message: 'OK' | 'ERROR';
  error?: string;
}

If message = 'ERROR', then error field is present.

Problem, when response is success (message = 'OK'). Error property does not present, and another properties is.

type SomeAnotherResponse = MainTypeResponse & {
  prop1: 'string';
  prop2: ''number;
}

I tried to union types (error)

type SomeAnotherResponse = MainTypeResponse | {
  message: MainTypeResponse['message']
  prop1: 'string';
  prop2: ''number;
}

I don't want to condition it prop1?: string

In code, i want to check it with this construction

const result: SomeAnotherResponse = '...'
if (result.message === 'OK') {
  // ts error 
  console.log(result.prop1);
}

So, something like

type SomeAnotherResponse<T> = T extends {message: 'OK'} ? {} : {}

Solution

  • The simplest approach is to just define two separate types, and then create a union of those types. TypeScript will correctly narrow the type based on the value of the discriminator property:

    type SuccessResponse = {
        message: 'OK';
        prop1: string;
        prop2: number;
    };
    
    type ErrorResponse = {
        message: 'ERROR';
        error: string;
    }
    
    type MainResponse = SuccessResponse | ErrorResponse;
    
    function handleResponse(response: MainResponse) {
        if (response.message === 'OK') {
            console.log(response.prop1); // OK
            console.log(response.error); // Error
        }
    }
    

    Playground link

    The handbook refers to this as a discriminated union.