@skyroc/type-utils
Version:
Advanced TypeScript utility types for form handling, path manipulation, and type transformations
573 lines (450 loc) • 11.7 kB
Markdown
# Skyroc Type Utils
English | [简体中文](./README.zh.md)
Advanced TypeScript utility types for form handling, path manipulation, and type transformations. Provides a comprehensive collection of type utilities to enhance TypeScript's type system with powerful type-level programming capabilities.
## ✨ Features
- 🎯 **Advanced Type Utilities** - Rich collection of utility types for complex type transformations
- 📝 **Form Type Support** - Specialized types for form elements and custom components
- 🛤️ **Path Manipulation** - Type-safe path types for nested object access
- 🔧 **Function Type Helpers** - Extract and manipulate function types from objects
- 💪 **Deep Type Operations** - Deep partial, deep optional, and nested type utilities
- 🎨 **Type Prettification** - Make complex intersection types readable in IDE
- ⚡ **Zero Runtime** - All utilities are type-level only, zero runtime overhead
## 📦 Installation
```bash
npm install @skyroc/type-utils
# or
pnpm add @skyroc/type-utils
# or
yarn add @skyroc/type-utils
```
## 🚀 Quick Start
```typescript
import type {
DeepPartial,
LeafPaths,
PathToType,
OnlyFunctions,
Prettify
} from '@skyroc/type-utils';
// Deep partial for nested objects
type User = {
name: string;
address: {
city: string;
street: string;
};
};
type PartialUser = DeepPartial<User>;
// { name?: string; address?: { city?: string; street?: string } }
// Type-safe paths for nested properties
type UserPaths = LeafPaths<User>;
// "name" | "address.city" | "address.street"
// Get type from path
type CityType = PathToType<User, "address.city">; // string
// Extract only function properties
type API = {
data: string;
fetch(): Promise<void>;
update(id: number): void;
};
type APIFunctions = OnlyFunctions<API>;
// { fetch: () => Promise<void>; update: (id: number) => void }
```
## 📚 API Reference
### Function Type Utilities
#### `Fn`
Generic function type.
```typescript
type Fn = (...args: any[]) => any;
```
#### `Noop`
No-operation function type.
```typescript
type Noop = () => void;
```
#### `OnlyFunctions<T>`
Extracts only function properties from an object type.
```typescript
interface Foo {
a: number;
b?: string;
c(): void;
d: (x: number) => string;
e?: () => void;
}
type FooFunctions = OnlyFunctions<Foo>;
// {
// c: () => void;
// d: (x: number) => string;
// e?: (() => void) | undefined;
// }
```
#### `FunctionKeys<T>`
Extracts keys of function properties from an object type.
```typescript
interface Foo {
a: number;
b?: string;
c(): void;
d: (x: number) => string;
e?: () => void;
}
type FooFnKeys = FunctionKeys<Foo>; // 'c' | 'd' | 'e'
```
#### `FunctionUnion<T>`
Creates a union of all function types in an object.
```typescript
interface Foo {
a: number;
c(): void;
d: (x: number) => string;
e?: () => void;
}
type FooFnUnion = FunctionUnion<Foo>;
// (() => void) | ((x: number) => string) | ((() => void) | undefined)
```
### Form Type Utilities
#### `CustomElement<T>`
Represents a custom form element with common input properties.
```typescript
type CustomElement<T = any> = Partial<HTMLElement> & T & {
checked?: boolean;
disabled?: boolean;
files?: FileList | null;
focus?: Noop;
options?: HTMLOptionsCollection;
type?: string;
value?: any;
};
```
#### `FieldElement<T>`
Union type for all possible field elements including HTML inputs and custom elements.
```typescript
type FieldElement<T = any> =
| HTMLInputElement
| HTMLSelectElement
| HTMLTextAreaElement
| CustomElement<T>;
// Usage in form handlers
function handleFieldChange(field: FieldElement) {
console.log(field.value);
}
```
### Path Type Utilities
#### `LeafPaths<T>`
Generates a union of all possible paths to leaf (non-object) values in a type.
```typescript
type FormValues = {
age: number;
code: string;
info: {
age: number;
city: string;
name: string;
};
items: {
id: number;
label: string;
}[];
};
type Paths = LeafPaths<FormValues>;
// "age"
// | "code"
// | "info.age"
// | "info.city"
// | "info.name"
// | `items.${number}.id`
// | `items.${number}.label`
```
#### `AllPaths<T>`
Generates a union of all possible paths including intermediate object paths.
```typescript
type FormValues = {
age: number;
info: {
city: string;
address: {
street: string;
};
};
};
type Paths = AllPaths<FormValues>;
// "age"
// | "info"
// | "info.city"
// | "info.address"
// | "info.address.street"
```
#### `PathToType<T, P>`
Gets the type at a specific path, making object properties optional.
```typescript
type FormValues = {
age: number;
info: {
age: number;
city: string;
address: {
street: string;
};
};
items: {
id: number;
name: string;
}[];
};
type AgeType = PathToType<FormValues, "age">; // number
type InfoType = PathToType<FormValues, "info">;
// { age?: number; city?: string; address?: { street: string } | undefined }
type ItemType = PathToType<FormValues, "items.0">;
// { id?: number; name?: string }
```
#### `PathToDeepType<T, P>`
Gets the type at a specific path, making all nested properties deeply optional.
```typescript
type FormValues = {
info: {
age: number;
address: {
street: string;
city: string;
};
};
};
type InfoType = PathToDeepType<FormValues, "info">;
// {
// age?: number;
// address?: {
// street?: string;
// city?: string;
// } | undefined;
// }
```
#### `ShapeFromPaths<T, Ps>`
Creates a new type containing only the specified paths from the original type.
```typescript
type FormValues = {
age: number;
code: string;
info: {
age: number;
city: string;
name: string;
};
items: {
id: number;
label: string;
}[];
};
type PartialShape = ShapeFromPaths<FormValues, ['age', 'info', 'items.2.label']>;
// {
// age: number;
// info: { age?: number; city?: string; name?: string };
// items: { label?: string }[];
// }
```
#### `ArrayKeys<T>`
Extracts keys that are array types from an object.
```typescript
type Inputs = {
password: string;
username: string;
numbers: number[];
users: {
age: number;
name: string;
}[];
};
type Arrays = ArrayKeys<Inputs>; // "numbers" | "users"
```
#### `ArrayElementValue<T, K>`
Gets the element type of an array property.
```typescript
type Inputs = {
users: {
age: number;
name: string;
}[];
};
type UserType = ArrayElementValue<Inputs, "users">;
// { age: number; name: string }
```
### General Utility Types
#### `DeepPartial<T>`
Makes all properties of a type optional recursively.
```typescript
type User = {
name: string;
age: number;
address: {
city: string;
street: string;
zipCode: number;
};
};
type PartialUser = DeepPartial<User>;
// {
// name?: string;
// age?: number;
// address?: {
// city?: string;
// street?: string;
// zipCode?: number;
// };
// }
```
#### `Prettify<T>`
Flattens intersection types to make them more readable in IDE tooltips.
```typescript
type A = { a: number };
type B = { b: string };
type C = { c: boolean };
type Raw = A & B & C;
// When hovering: A & B & C (not readable)
type Pretty = Prettify<A & B & C>;
// When hovering: { a: number; b: string; c: boolean } (readable!)
```
#### `Primitive`
Union of all primitive types.
```typescript
type Primitive =
| string
| number
| boolean
| bigint
| symbol
| null
| undefined
| Date
| Function;
```
#### `Wrap<K, V>`
Wraps a value in an object with a specific key.
```typescript
type Wrapped = Wrap<"data", number>; // { data: number }
type User = Wrap<"user", { name: string; age: number }>;
// { user: { name: string; age: number } }
```
#### `MergeUnion<U>`
Merges a union of object types into a single intersection type.
```typescript
type Union = { a: number } | { b: string } | { c: boolean };
type Merged = MergeUnion<Union>;
// { a: number; b: string; c: boolean }
```
#### `KeyToNestedObject<K, V>`
Converts a dot-notation key into a nested object type.
```typescript
type Nested = KeyToNestedObject<"a.b.c", number>;
// { a: { b: { c: number } } }
type UserPath = KeyToNestedObject<"user.profile.email", string>;
// { user: { profile: { email: string } } }
```
## 🎯 Common Use Cases
### Type-Safe Form Handling
```typescript
import type { LeafPaths, PathToType, FieldElement } from '@skyroc/type-utils';
type UserForm = {
username: string;
email: string;
profile: {
firstName: string;
lastName: string;
age: number;
};
addresses: {
street: string;
city: string;
}[];
};
// Type-safe field paths
type FieldPath = LeafPaths<UserForm>;
// "username" | "email" | "profile.firstName" | ...
// Get field value type from path
function getFieldValue<P extends FieldPath>(
form: UserForm,
path: P
): PathToType<UserForm, P> {
// Implementation...
}
// Usage with full type safety
const age = getFieldValue(form, "profile.age"); // number
const city = getFieldValue(form, "addresses.0.city"); // string
```
### Extract API Methods
```typescript
import type { OnlyFunctions, FunctionKeys } from '@skyroc/type-utils';
interface UserService {
currentUser: User | null;
isLoading: boolean;
fetchUser(id: number): Promise<User>;
updateUser(user: User): Promise<void>;
deleteUser(id: number): Promise<void>;
settings: {
timeout: number;
};
}
// Extract only methods
type UserServiceMethods = OnlyFunctions<UserService>;
// {
// fetchUser: (id: number) => Promise<User>;
// updateUser: (user: User) => Promise<void>;
// deleteUser: (id: number) => Promise<void>;
// }
// Get method names
type MethodNames = FunctionKeys<UserService>;
// "fetchUser" | "updateUser" | "deleteUser"
```
### Partial Form Updates
```typescript
import type { DeepPartial, ShapeFromPaths } from '@skyroc/type-utils';
type UserProfile = {
personal: {
firstName: string;
lastName: string;
email: string;
};
settings: {
notifications: boolean;
theme: 'light' | 'dark';
};
};
// Allow partial updates
function updateProfile(updates: DeepPartial<UserProfile>) {
// Can update any nested property partially
}
updateProfile({
personal: {
firstName: "John" // Only update firstName
}
});
// Or select specific fields
type ProfilePaths = ['personal.firstName', 'personal.email', 'settings.theme'];
type UpdateableFields = ShapeFromPaths<UserProfile, ProfilePaths>;
function updateSpecificFields(updates: UpdateableFields) {
// Only allows updating specified paths
}
```
### Readable Type Aliases
```typescript
import type { Prettify } from '@skyroc/type-utils';
// Without Prettify - hard to read
type UserWithRole = User & { role: string } & { permissions: string[] };
// With Prettify - clean and readable
type CleanUserWithRole = Prettify<User & { role: string } & { permissions: string[] }>;
// Hover shows: { id: number; name: string; role: string; permissions: string[] }
```
## 📖 TypeScript Support
This package is designed specifically for TypeScript and requires TypeScript 4.7 or higher for full functionality. All types are fully documented with JSDoc comments for excellent IDE support.
```typescript
// Excellent autocomplete and type hints
import type {
LeafPaths, // ← IDE shows full documentation
PathToType, // ← With usage examples
DeepPartial // ← And type definitions
} from '@skyroc/type-utils';
```
## 📄 License
MIT License
## 🔗 Links
- [GitHub Repository](https://github.com/Ohh-889/skyroc-ui)
- [Issue Tracker](https://github.com/Ohh-889/skyroc-ui/issues)