Skip to main content

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.