Search code examples
javascripttypescripttypestypescript-conditional-types

Conditional types in TypeScript


I was wondering if I can have conditional types in TypeScript?

Currently I have the following interface:

interface ValidationResult {
  isValid: boolean;
  errorText?: string;
}

But I want to remove errorText, and only have it when isValid is false as a required property.

I wish I was able to write it as the following interface:

interface ValidationResult {
  isValid: true;
}

interface ValidationResult {
  isValid: false;
  errorText: string;
}

But as you know, it is not possible. So, what is your idea about this situation?


Solution

  • One way to model this kind of logic is to use a union type, something like this

    interface Valid {
      isValid: true
    }
    
    interface Invalid {
      isValid: false
      errorText: string
    }
    
    type ValidationResult = Valid | Invalid
    
    const validate = (n: number): ValidationResult => {
      return n === 4 ? { isValid: true } : { isValid: false, errorText: "num is not 4" }
    }
    

    The compiler is then able to narrow the type down based on the boolean flag

    const getErrorTextIfPresent = (r: ValidationResult): string | null => {
      return r.isValid ? null : r.errorText
    }