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
- 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.
- 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.

