Installation
Install duck-ttest, configure tsconfig, and import your first sub-path.
Prerequisites
- TypeScript 5.0+. Several utilities rely on
infer ... extends ...constraints and const type parameters. - A
tscinvocation as part of your test or CI step.tsc --noEmitis the entire runner. - Bun, npm, pnpm, or yarn — duck-ttest is a plain TypeScript-only package.
Install
Install the package
# bun
bun add -d @gentleduck/ttest
# npm
npm install --save-dev @gentleduck/ttest
# pnpm
pnpm add -D @gentleduck/ttest
# yarn
yarn add -D @gentleduck/ttest
duck-ttest is a devDependency — its types are erased at compile time, so it never reaches your production bundle.
Import a sub-path
import type { AssertTrue, AssertFalse } from '@gentleduck/ttest/assert'
import type { Equal, NotEqual } from '@gentleduck/ttest/equality'
import type { IsAny, IsNever } from '@gentleduck/ttest/any'
Every module has its own sub-path. Importing from a sub-path keeps unrelated utility types out of the type-checker's cache.
Write an assertion
type _t = AssertTrue<Equal<IsAny<unknown>, false>, 'unknown should not be any'>
If the assertion holds, the type-check succeeds silently. If it fails, the message string surfaces as the error.
TypeScript configuration
{
"compilerOptions": {
"strict": true,
"moduleResolution": "bundler"
}
}
strict is required because many utilities depend on strict null checks. bundler (or node16/nodenext) is required for sub-path exports to resolve.
Sub-path exports
import type { AssertTrue, AssertFalse } from '@gentleduck/ttest/assert'
import type { Equal, NotEqual, ShallowEqual } from '@gentleduck/ttest/equality'
import type { IsAny, IsNever, IsUnknown, IsVoid, NotAny } from '@gentleduck/ttest/any'
import type { And, Or, Not, Xor, Xnor } from '@gentleduck/ttest/boolean'
import type { If, IfExtends, Switch, Match } from '@gentleduck/ttest/conditional'
import type { Brand, Unbrand, BrandOf, Opaque, Tagged } from '@gentleduck/ttest/brand'
import type { Primitive, Falsy, NonNullish, Builtin, IsOptional } from '@gentleduck/ttest/primitive'
import type { Simplify, DeepPartial, DeepReadonly, Get, Paths, KebabCaseKeys } from '@gentleduck/ttest/object'
import type { Head, Tail, Last, Zip, Append, Prepend, Length } from '@gentleduck/ttest/tuple'
import type { UnionToIntersection, XOR } from '@gentleduck/ttest/union'
import type { InferSchema, SQLTypeMap, IsSQLOptional } from '@gentleduck/ttest/sql'
import type { PathParams, BuildPath, MatchRoute, QueryParams } from '@gentleduck/ttest/router'
import type { Fn, Apply, MapTuple, Reduce, ComposeFn } from '@gentleduck/ttest/fp'
import type { Ok, Err, Result, Option, IsOk, UnwrapOk } from '@gentleduck/ttest/result'
import type { Emitter, EventMap, Handlers } from '@gentleduck/ttest/emitter'
// ...and so on for any / aria / async / bit / class / css / date /
// discriminated / extraction / format / fs / function / geometry / guard /
// http / json / literal / locale / number / pattern / predicates / promise / template
Always use import type (or enable verbatimModuleSyntax) — every export is a pure type.
Verifying your install
Drop the following file anywhere covered by your tsconfig.json and run tsc --noEmit.
import type { AssertTrue, AssertFalse } from '@gentleduck/ttest/assert'
import type { Equal } from '@gentleduck/ttest/equality'
import type { IsAny, IsNever } from '@gentleduck/ttest/any'
type t1 = AssertTrue<Equal<IsAny<any>, true>, 'any should be any'>
type t2 = AssertTrue<Equal<IsNever<never>, true>, 'never should be never'>
type t3 = AssertFalse<Equal<1, 2>, '1 must not equal 2'>
If the type-check passes, the install is correct.
Next steps
- Getting started — a five-minute tutorial.
- Core / Assertions — the full assertion API.
- API reference — every exported type, grouped by module.