boolean
Logical operators on type-level booleans.
import type { And, Or, Not, Xor, Xnor, If } from '@gentleduck/ttest/boolean'
The standard boolean truth table on type-level true / false, plus a re-export of If for ergonomic grouping. Use these to compose larger predicates from the Is* helpers in any, guard, and predicates.
And
type And<A extends boolean, B extends boolean>
Logical AND. true only when both inputs are exactly true.
type a = And<true, true> // true
type b = And<true, false> // false
type c = And<false, true> // false
type d = And<false, false> // false
import type { IsString } from '@gentleduck/ttest/guard'
import type { IsLiteral } from '@gentleduck/ttest/literal'
type IsStringLit<T> = And<IsString<T>, IsLiteral<T>>
type a = IsStringLit<'hi'> // true
type b = IsStringLit<string> // false
Or
type Or<A extends boolean, B extends boolean>
Logical OR. true when either input is exactly true.
type a = Or<true, false> // true
type b = Or<false, true> // true
type c = Or<false, false> // false
Not
type Not<A extends boolean>
Logical negation.
type a = Not<true> // false
type b = Not<false> // true
Edge case: Not<boolean> is boolean — the distribution over true | false flips each member back to a union of both.
Xor
type Xor<A extends boolean, B extends boolean>
Exclusive OR — true iff exactly one input is true. Useful for "one or the other but not both" assertions.
type a = Xor<true, false> // true
type b = Xor<false, true> // true
type c = Xor<true, true> // false
type d = Xor<false, false> // false
Xnor
type Xnor<A extends boolean, B extends boolean> = Not<Xor<A, B>>
Exclusive NOR — true iff both inputs are equal. Equivalent to type-level equality on boolean.
type a = Xnor<true, true> // true
type b = Xnor<false, false> // true
type c = Xnor<true, false> // false
If
Re-exported from conditional. Type-level ternary kept here for ergonomic grouping with boolean operators.
type If<Cond extends boolean, Then, Else> = Cond extends true ? Then : Else
type Branch<C extends boolean> = If<C, 'yes', 'no'>
type a = Branch<true> // 'yes'
type b = Branch<false> // 'no'
Edge case: every boolean operator here constrains both generics to boolean. Passing boolean (the union true | false) distributes — the result is also boolean. Pin to a literal first if that is not what you want.