Skip to content
webtype.orgwebtype.orgTS1110

    ↑↓ move · ⏎ open · esc close

    TS1110

    A conditional with no else

    Type expected.

    The compiler’s own words. Not translated — this is the string you pasted into a search box.

    A conditional type must say what happens when the check fails. There is no optional else at the type level, because every type has to resolve to something.

    Reproduction

    type Digit = '0' | '1' | '2'
    
    type IsDigit<T extends string> = T extends Digit ? true :

    The build asserts this emits exactly this code.

    Why the compiler says this

    An `if` may do nothing when its condition is false; a conditional type may not, because the whole expression has to name a type either way. `T extends U ? X : Y` is the only shape there is — the `:` is not optional punctuation but the branch that answers "and otherwise". Like TS1109 this comes from the parser, so it is reported before a single type is resolved, and the message names what the grammar wanted rather than what you were building.

    Fixes

    1. 01
      type Digit = '0' | '1' | '2'
      
      type IsDigit<T extends string> = T extends Digit ? true : false
      
      type Yes = IsDigit<'1'>
      type No = IsDigit<'x'>

      Answer the question. A predicate wants `false` in the other branch, and then it is a boolean for every input rather than for some of them.

    2. 02
      type Digit = '0' | '1' | '2'
      
      type OnlyDigits<T extends string> = T extends Digit ? T : never
      
      type Kept = OnlyDigits<'1' | 'x' | '2'>

      Or use `never` as the else, which is how you filter a union: the members that fail the check contribute nothing and vanish from the result.

    Takeaway

    `never` is the else branch you want more often than you expect. It is not an error value — it is the absence that makes a distributive conditional behave like a filter.

    Where to go next

    Errors