TypeScript Helper Types Collection
helpertypes is a lightweight collection of general-purpose TypeScript helper types designed to simplify complex type manipulations across various projects. As of version `0.0.19`, the library offers utilities like deep partial/required types, object key pickers, and string lookup types. The project maintains an active development status, with frequent releases (often multiple per month) focused on introducing new helper types and refining the behavior and robustness of existing ones, particularly for deep type transformations. Its key differentiators include its small footprint, focused scope on just type utilities without runtime code, and a commitment to providing common, reusable type patterns that might otherwise be cumbersome to implement from scratch. While still in a pre-1.0 state, it's regularly updated with fixes and new features.
Common errors
-
Type instantiation is excessively deep and possibly infinite.
cause Using complex recursive helper types (like `PartialDeep`, `RequiredDeep`, or `ObjectLookupTuple`) from `helpertypes` on very deeply nested object structures or with older versions of the library, hitting TypeScript's default recursion depth limit.fixUpgrade `helpertypes` to the latest version (v0.0.19+), as many recursion issues have been fixed. If the problem persists with extremely deep types, consider manually increasing TypeScript's `--declarationDir` or `--maxNodeModuleJsDepth` compiler options, though this is often a sign of overly complex types. -
TypeError: (0 , helpertypes_1.PartialDeep) is not a function
cause Attempting to import a type from `helpertypes` as if it were a runtime value in an ESM context, leading to a failed runtime import and execution.fixChange the import statement from `import { PartialDeep } from 'helpertypes';` to `import type { PartialDeep } from 'helpertypes';`. This explicitly tells TypeScript to only import the type definition, which is correctly stripped at compile time.
Warnings
- gotcha The `RequiredDeep` and `PartialDeep` types have undergone several bug fixes across minor versions (e.g., v0.0.16, v0.0.17). Users relying on their behavior in older versions might encounter subtle changes in type inference or edge case handling, especially with deeply nested or complex types. Ensure thorough type checking when upgrading.
- breaking The implementation of `ObjectLookupTuple` was replaced in v0.0.18 to address issues where it could exceed TypeScript's allowed recursive call limits, leading to compilation errors or incorrect type inference. While a fix, code that might have (erroneously) compiled with the previous, less robust implementation due to recursion limits might now behave differently or resolve types correctly.
- gotcha As a type-only library, `helpertypes` exports no runtime values. Attempting to `import { SomeType } from 'helpertypes';` without `type` or using `require()` will result in runtime errors (e.g., `TypeError: (0 , helpertypes_1.PartialDeep) is not a function` in ESM contexts or `undefined` in CJS) or TypeScript compiler warnings.
Install
-
npm install helpertypes -
yarn add helpertypes -
pnpm add helpertypes
Imports
- PartialDeep
import { PartialDeep } from 'helpertypes';import type { PartialDeep } from 'helpertypes'; - RequiredDeep
const { RequiredDeep } = require('helpertypes');import type { RequiredDeep } from 'helpertypes'; - ObjectLookupString
import type { ObjectLookupString } from 'helpertypes';
Quickstart
import type { PartialDeep, RequiredDeep, ObjectLookupString } from 'helpertypes';
interface UserProfile {
id: string;
name: string;
settings: {
theme: 'dark' | 'light';
notifications: boolean;
};
tags?: string[];
}
// Create a deeply partial version of UserProfile
type PartialUserProfile = PartialDeep<UserProfile>;
const partialUser: PartialUserProfile = {
id: 'abc-123',
settings: { theme: 'dark' } // Only define some nested properties
};
console.log(partialUser);
// Create a deeply required version, making all optional properties required (if possible)
type FullyRequiredUserProfile = RequiredDeep<UserProfile>;
const fullUser: FullyRequiredUserProfile = {
id: 'def-456',
name: 'Jane Doe',
settings: { theme: 'light', notifications: true },
tags: [] // 'tags' is now required
};
console.log(fullUser);
interface NestedObject {
a: { b: { c: string } };
d: number;
}
// Look up a string path in a nested object type
type PathA_B_C = ObjectLookupString<NestedObject, 'a.b.c'>; // Expected: string
type PathD = ObjectLookupString<NestedObject, 'd'>; // Expected: number
// Type checking for example usage (won't run in JS)
const val1: PathA_B_C = 'hello';
// @ts-expect-error - Type 'number' is not assignable to type 'string'.
const val2: PathA_B_C = 123;
console.log('Demonstrating type utilities. Check TypeScript compiler for full effect.');