mrkeyoor.com_
Sun 20 Sept 02:40 UTC
npmUtilsupdated 19 Sept 2026

type-fest review

type-fest 5.8.0 is a declaration-only set of TypeScript utility types. It covers stricter object omission, deep transforms, tagged values, JSON-safe shapes, path types, exclusive properties, string manipulation, package.json, and tsconfig data. Nothing in the package runs after compilation. Version 5.8.0 adds `StringToArray`, `StringLength`, `StringToNumber`, and `ExtractExactly`, extends `StringRepeat`, and fixes optional tuple handling plus Schema fields containing `any` or `unknown`. The README requires TypeScript 5.9 or later, ESM conventions, and strict mode.

344.8Mdownloads / wk
Verdict

type-fest 5.8.0 took 0.4 seconds and 2 MB to install in our sandbox, but both Node import forms and the browser bundle failed because the package provides types with no runtime entry point. Add it as a type-only dependency for strict TypeScript 5.9 projects, and leave it out when built-in utilities or a plain domain interface are easier to maintain.

We installed it

Lab card: what happened when we installed type-festScreenshot of type-fest documentation
Install✓ · 0.4s2 packages on disk · 2 MB
ImportESM import fails · require() fails · ESM package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does type-fest install cleanly?

Yes. In a fresh container with an empty cache, npm install type-fest finished in 0.4s, leaving 2 packages and 2 MB on disk. npm audit reported no known vulnerabilities.

Can type-fest run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does type-fest work with both ESM and CommonJS?

Neither plain import nor require succeeded in our sandbox, so it needs a bundler or extra setup.

Does type-fest include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

type-fest or ts-toolbelt: which should you use?

ts-toolbelt: Use it when its larger object, tuple, union, and function type modules better match the type-level work. type-fest 5.8.0 took 0.4 seconds and 2 MB to install in our sandbox, but both Node import forms and the browser bundle failed because the package provides types with no runtime entry point.

When should you not use type-fest?

The compiler is older than TypeScript 5.9, strict mode is disabled, or the project cannot follow the package's ESM requirement.

API stability3/5Export names are documented and many survive across minor releases, but conditional types can change behavior without a runtime signature to protect callers. Major versions also raise TypeScript, Node, strictness, and module requirements. Version 5.8.0 adds four types and corrects Schema, optional tuple, and StringRepeat behavior. A source import may remain valid while assignability or compiler cost changes, so public libraries need pinned compiler versions and type-level regression tests.
Docs5/5The README groups exported types by purpose, links each name to its declaration, includes focused examples, lists alternative names, and records declined proposals with reasons. It states TypeScript 5.9, ESM, and strict-mode requirements near installation. Release 5.8.0 names each addition and repaired edge case. Choosing between similar deep, exact, union, and path helpers still takes source reading, but the reference does not hide the constraints or pretend declarations perform runtime checks.
Maintenance5/5Version 5.8.0 was released on July 4, 2026, and GitHub showed the unarchived repository pushed on August 26, 2026 with 225 open issues and pull requests. Recent releases add utilities made possible by current TypeScript and fix compiler-sensitive edge cases in tuples, schemas, string operations, unions, and paths. The fast compiler floor is a migration cost, yet it comes with current language support and active tests rather than an abandoned declaration bundle.
Ecosystem5/5The npm downloads endpoint counted 382,162,176 downloads from August 19 through August 25, 2026, and GitHub reports 17,381 stars. Many TypeScript packages consume or re-export its definitions, and some ideas later reach the standard TypeScript utility library. That reach can become coupling when public declarations expose type-fest types. Our runtime checks failed by design, so adoption belongs in the compiler and editor workflow rather than production execution.

Discussed on

  1. hnType-fest – A collection of essential TypeScript types3 points

Use it if

  • A strict TypeScript 5.9 project repeatedly needs deep, conditional, branded, or mutually exclusive type transformations.
  • A public API benefits from JSON-compatible types, tagged identifiers, or package.json and tsconfig declarations.
  • The team wants a reviewed conditional type instead of maintaining the same difficult definition in several packages.
  • Intersections and mapped types need `Simplify` so editor hovers show the resulting object shape.
Skip it if

Setup reality

We installed type-fest 5.8.0 in a fresh Node 22 Bookworm sandbox. npm completed in 0.4 seconds and left two packages using 2 MB. The package declares one direct dependency, zero peer dependencies, Node 20 or later, and (MIT OR CC0-1.0) licensing. Our measured package reported 1,108 KB unpacked and bundled TypeScript declarations. npm audit found zero vulnerabilities at every severity.

The package is marked ESM and has an exports map containing type declarations only. Under Node 22.23.2, both require('type-fest') and dynamic ESM import('type-fest') failed in our sandbox. An esbuild browser bundle failed too, so there is no browser size to report. These outcomes match a types-only dependency: there is no JavaScript entry point for Node or a browser to execute. Use import type and keep it out of runtime code paths.

The README requires TypeScript 5.9 or later and strict: true. An older compiler can fail inside declaration files even when application code did not change, so align the type-fest pin with the compiler used in CI. Begin with TypeScript's built-in utilities. Apply deep, path, exactness, and union transforms at narrow boundaries, then inspect tsc --extendedDiagnostics if a widely instantiated generic slows editor or build checking.

Every type disappears from emitted JavaScript. Tagged does not check an ID prefix, ReadonlyDeep does not freeze an object, and PackageJson does not validate parsed JSON. Add runtime checks where data crosses a trust boundary. Conditional assignability also changes with inference and compiler releases, so keep positive assignments and @ts-expect-error rejections in type tests before upgrading from 5.8.0.

Patterns

Remove only known object keys strict-omit

import type {Except} from 'type-fest';

type Post = {
  id: string;
  title: string;
  draft: boolean;
};

type PublishedPost = Except<Post, 'draft'>;

`Except` can enforce known omitted keys more strictly than a casually widened key union. It changes only static assignability.

Model later object properties winning merge-types

import type {Merge} from 'type-fest';

type Defaults = {
  timeout: number;
  retries: number;
};
type Overrides = {timeout?: string};

type Config = Merge<Defaults, Overrides>;

`Merge` models override precedence. Application code must still perform the actual object spread or merge at runtime.

Describe nested configuration patches partial-deep

import type {PartialDeep} from 'type-fest';

type Settings = {
  server: {host: string; port: number};
  features: {darkMode: boolean};
};

function applyPatch(patch: PartialDeep<Settings>) {
  return mergeSettings(patch);
}

Deep optionality can cost more compiler work on large recursive models. Prefer a small explicit patch interface when the accepted fields are known.

Reject nested writes during checking readonly-deep

import type {ReadonlyDeep} from 'type-fest';

type State = {
  user: {name: string};
  tags: string[];
};

const state: ReadonlyDeep<State> = {
  user: {name: 'Ada'},
  tags: ['admin'],
};

`ReadonlyDeep` does not call Object.freeze. JavaScript can still mutate the value through untyped or cast code.

Change optionality for selected keys selected-optionality

import type {SetOptional, SetRequired} from 'type-fest';

type User = {
  id: string;
  email: string;
  nickname?: string;
};

type NewUser = SetOptional<User, 'id'>;
type CompleteUser = SetRequired<User, 'nickname'>;

These helpers preserve every unselected property and state the changed keys directly, which is clearer than stacked mapped intersections.

Flatten an intersection for editor display simplify-intersection

import type {Simplify} from 'type-fest';

type Base = {id: string};
type Named = {name: string};

type User = Simplify<Base & Named>;

`Simplify` improves hover presentation and some assignability views. It creates no object and changes no emitted JavaScript.

Separate identifiers with static tags tag-identifiers

import type {Tagged} from 'type-fest';

type UserId = Tagged<string, 'UserId'>;
type OrderId = Tagged<string, 'OrderId'>;

function loadUser(id: UserId) {
  return users.get(id);
}

const userId = parseUserId('usr_42');
loadUser(userId);

The parser or constructor must validate the string before tagging it. A type assertion can forge either ID with no runtime check.

Restrict a boundary to JSON values json-values

import type {JsonValue} from 'type-fest';

function writePayload(value: JsonValue): string {
  return JSON.stringify(value);
}

writePayload({ok: true, items: [1, 2, 3]});

`JsonValue` checks static inputs but cannot inspect an `any` value or data received after compilation. Validate untrusted payloads.

Type package.json after validation package-json-type

import type {PackageJson} from 'type-fest';
import {readFile} from 'node:fs/promises';

const raw: unknown = JSON.parse(
  await readFile('package.json', 'utf8')
);
const pkg: PackageJson = validatePackageJson(raw);
console.log(pkg.dependencies ?? {});

The validation function matters. Casting JSON directly to `PackageJson` would only silence the compiler.

Require exactly one credential form exclusive-properties

import type {MergeExclusive} from 'type-fest';

type ApiKeyAuth = {apiKey: string};
type TokenAuth = {token: string};

type Auth = MergeExclusive<ApiKeyAuth, TokenAuth>;

function connect(auth: Auth) {
  // one credential form is allowed
}

The type prevents callers from supplying both keys during checking. Runtime input still needs the same exclusivity validation.

Constrain dotted object paths typed-paths

import type {Get, Paths} from 'type-fest';

type Config = {
  server: {host: string; port: number};
  flags: {darkMode: boolean};
};

function readPath<P extends Paths<Config>>(
  value: Config,
  path: P,
): Get<Config, P> {
  return runtimeGet(value, path) as Get<Config, P>;
}

`Paths` and `Get` can be expensive on large recursive shapes. The runtime path walker must match the same dotted-path semantics.

Measure a string literal type string-literal-length

import type {StringLength, StringToArray} from 'type-fest';

type Code = 'ABC42';
type CodeLength = StringLength<Code>;
type CodeCharacters = StringToArray<Code>;

const length: CodeLength = 5;

`StringLength` and `StringToArray` are new in 5.8.0. General `string` values remain runtime strings rather than fixed compile-time literals.

Alternatives

PackageRegistryPick it when
ts-toolbeltnpmUse it when its larger object, tuple, union, and function type modules better match the type-level work.
utility-typesnpmChoose it for an older, smaller collection spanning TypeScript and legacy Flow utility aliases.
type-plusnpmCompare it when you want a different maintained collection of type-level helpers and assertions.

More utils guides

lru-cache · ajv · p-limit · find-up · js-yaml · zod · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.