uni-types 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,46 +1,82 @@
1
- <div style="text-align: center;" align="center">
1
+ <div align="center">
2
2
 
3
3
  # uni-types
4
4
 
5
- Universal TypeScript type utilities - A comprehensive collection of type helpers for TypeScript development
5
+ **Universal TypeScript Type Utilities**
6
6
 
7
- English | [简体中文](./README_CN.md)
7
+ A comprehensive collection of type helpers for TypeScript development
8
8
 
9
9
  [![NPM version][npm-image]][npm-url]
10
- ![typescript][typescript-url]
11
- [![Test coverage][codecov-image]][codecov-url]
12
- [![npm download][download-image]][download-url]
10
+ [![NPM downloads][download-image]][download-url]
11
+ ![TypeScript][typescript-url]
12
+ [![Codecov][codecov-image]][codecov-url]
13
13
  [![License][license-image]][license-url]
14
14
 
15
+ [**Documentation**](https://saqqdy.github.io/uni-types/) · [**中文文档**](./README_CN.md)
16
+
15
17
  </div>
16
18
 
19
+ ## Features
20
+
21
+ - 🎯 **100+ Type Utilities** - Comprehensive type helpers for every use case
22
+ - 🔒 **Type Safe** - Full TypeScript support with strict type checking
23
+ - 📦 **Zero Dependencies** - Lightweight and tree-shakeable
24
+ - 🚀 **TypeScript 5.x** - Built with the latest TypeScript features
25
+ - 🌍 **Bilingual Docs** - Documentation in English and Chinese
26
+
17
27
  ## Installation
18
28
 
19
29
  ```bash
20
- # use pnpm
21
- $ pnpm add uni-types
30
+ # pnpm
31
+ pnpm add uni-types
22
32
 
23
- # use yarn
24
- $ yarn add uni-types
33
+ # yarn
34
+ yarn add uni-types
25
35
 
26
- # use npm
27
- $ npm install uni-types
36
+ # npm
37
+ npm install uni-types
28
38
  ```
29
39
 
30
- ## Usage
40
+ ## Quick Start
31
41
 
32
42
  ```typescript
33
- import type { PickRequired, DeepPartial, IsArray } from 'uni-types'
34
-
35
- // Use in your TypeScript projects
43
+ import type {
44
+ PickRequired,
45
+ DeepPartial,
46
+ IsArray,
47
+ Brand,
48
+ If,
49
+ Paths
50
+ } from 'uni-types'
51
+
52
+ // Core: Make specific properties required
36
53
  interface User {
37
54
  name?: string
38
55
  age?: number
39
56
  email: string
40
57
  }
41
58
 
42
- type RequiredNameUser = PickRequired<User, 'name'>
43
- // { name: string; age?: number; email: string }
59
+ type RequiredUser = PickRequired<User, 'name' | 'age'>
60
+ // { name: string; age: number; email: string }
61
+
62
+ // Deep: Make all nested properties optional
63
+ interface Config {
64
+ database: {
65
+ host: string
66
+ port: number
67
+ }
68
+ }
69
+
70
+ type PartialConfig = DeepPartial<Config>
71
+ // { database?: { host?: string; port?: number } }
72
+
73
+ // Brand: Create nominal types
74
+ type UserId = Brand<string, 'UserId'>
75
+ type OrderId = Brand<string, 'OrderId'>
76
+ // UserId and OrderId are not interchangeable!
77
+
78
+ // Conditional: Type-level logic
79
+ type Result = If<true, 'success', 'error'> // 'success'
44
80
  ```
45
81
 
46
82
  ## API Reference
@@ -54,19 +90,6 @@ type RequiredNameUser = PickRequired<User, 'name'>
54
90
  | `PickPartial<T, K>` | Make specified properties optional |
55
91
  | `OmitPartial<T, K>` | Make properties except specified ones optional |
56
92
 
57
- ```typescript
58
- interface User {
59
- name?: string
60
- age?: number
61
- email: string
62
- }
63
-
64
- PickRequired<User, 'name'> // { name: string; age?: number; email: string }
65
- OmitRequired<User, 'name'> // { name?: string; age: number; email: string }
66
- PickPartial<User, 'email'> // { name?: string; age?: number; email?: string }
67
- OmitPartial<User, 'email'> // { name: string; age: number; email?: string }
68
- ```
69
-
70
93
  ### Tuple Operations
71
94
 
72
95
  | Type | Description |
@@ -80,17 +103,6 @@ OmitPartial<User, 'email'> // { name: string; age: number; email?: string }
80
103
  | `TupleLength<T>` | Get tuple length |
81
104
  | `IsEmptyTuple<T>` | Check if tuple is empty |
82
105
 
83
- ```typescript
84
- Head<[1, 2, 3]> // 1
85
- Last<[1, 2, 3]> // 3
86
- Tail<[1, 2, 3]> // [2, 3]
87
- Init<[1, 2, 3]> // [1, 2]
88
- Reverse<[1, 2, 3]> // [3, 2, 1]
89
- Flatten<[1, [2, [3]]]> // [1, 2, 3]
90
- TupleLength<[1, 2, 3]> // 3
91
- IsEmptyTuple<[]> // true
92
- ```
93
-
94
106
  ### Deep Operations
95
107
 
96
108
  | Type | Description |
@@ -99,17 +111,8 @@ IsEmptyTuple<[]> // true
99
111
  | `DeepRequired<T>` | Make all nested properties required |
100
112
  | `DeepReadonly<T>` | Make all nested properties readonly |
101
113
  | `DeepMutable<T>` | Make all nested properties mutable |
102
-
103
- ```typescript
104
- interface Nested {
105
- a: { b: { c: string } }
106
- }
107
-
108
- DeepPartial<Nested> // { a?: { b?: { c?: string } } }
109
- DeepRequired<{ a?: { b?: string } }> // { a: { b: string } }
110
- DeepReadonly<Nested> // { readonly a: { readonly b: { readonly c: string } } }
111
- DeepMutable<{ readonly a: { readonly b: string } }> // { a: { b: string } }
112
- ```
114
+ | `DeepOmit<T, P>` | Omit properties by path |
115
+ | `DeepPick<T, P>` | Pick properties by path |
113
116
 
114
117
  ### Type Guards
115
118
 
@@ -121,80 +124,62 @@ DeepMutable<{ readonly a: { readonly b: string } }> // { a: { b: string } }
121
124
  | `IsAny<T>` | Check if type is `any` |
122
125
  | `IsNever<T>` | Check if type is `never` |
123
126
  | `IsUnknown<T>` | Check if type is `unknown` |
127
+ | `IsFunction<T>` | Check if type is a function |
128
+ | `IsAsyncFunction<T>` | Check if type is an async function |
124
129
 
125
- ```typescript
126
- IsArray<string[]> // true
127
- IsArray<string> // false
128
- IsTuple<[string, number]> // true
129
- IsTuple<string[]> // false
130
- IsEqual<string, string> // true
131
- IsEqual<string, number> // false
132
- ```
133
-
134
- ### Type Inference
130
+ ### Conditional Types *(v1.1.0)*
135
131
 
136
132
  | Type | Description |
137
133
  |------|-------------|
138
- | `Awaited<T>` | Unwrap Promise type recursively |
139
- | `ArrayElement<T>` | Get array element type |
140
- | `ValueOf<T>` | Get object value types |
141
- | `FunctionKeys<T>` | Get keys of function properties |
142
- | `NonFunctionKeys<T>` | Get keys of non-function properties |
143
- | `FirstParameter<T>` | Get first parameter type of function |
134
+ | `If<C, T, F>` | Type-level if-then-else |
135
+ | `Not<B>` | Logical NOT for boolean types |
136
+ | `And<A, B>` | Logical AND for boolean types |
137
+ | `Or<A, B>` | Logical OR for boolean types |
138
+ | `Assert<T, U>` | Type constraint assertion |
144
139
 
145
- ```typescript
146
- Awaited<Promise<string>> // string
147
- Awaited<Promise<Promise<number>>> // number
148
- ArrayElement<string[]> // string
149
- ValueOf<{ a: string; b: number }> // string | number
150
- FunctionKeys<{ name: string; onClick: () => void }> // 'onClick'
151
- NonFunctionKeys<{ name: string; onClick: () => void }> // 'name'
152
- ```
153
-
154
- ### Utility Types
140
+ ### Brand Types *(v1.1.0)*
155
141
 
156
142
  | Type | Description |
157
143
  |------|-------------|
158
- | `Merge<T, U>` | Merge two types (U overrides T) |
159
- | `NonNullable<T>` | Exclude `null` and `undefined` |
160
- | `Exclusive<T, K>` | Create mutually exclusive properties |
161
- | `NoNullish<T>` | Remove null/undefined from all properties |
162
- | `Nullable<T>` | Add `null` to type |
163
- | `Optional<T>` | Add `undefined` to type |
164
- | `Maybe<T>` | Add `null` and `undefined` to type |
165
- | `LoosePartial<T>` | Make all properties optional |
144
+ | `Brand<T, B>` | Create a branded type for nominal typing |
145
+ | `Unbrand<T>` | Extract underlying type from branded type |
166
146
 
167
- ```typescript
168
- Merge<{ a: string; b: number }, { b: boolean; c: string }>
169
- // { a: string; b: boolean; c: string }
147
+ ### Function Utilities *(v1.1.0)*
170
148
 
171
- NonNullable<string | null | undefined> // string
172
- Nullable<string> // string | null
173
- Optional<string> // string | undefined
174
- Maybe<string> // string | null | undefined
175
- ```
149
+ | Type | Description |
150
+ |------|-------------|
151
+ | `Parameters<T>` | Get function parameters as tuple |
152
+ | `ReturnType<T>` | Get function return type |
153
+ | `NthParameter<T, N>` | Get Nth parameter type |
154
+ | `AsyncReturnType<T>` | Extract async function return type |
155
+ | `ThisParameterType<T>` | Get `this` parameter type |
156
+ | `OmitThisParameter<T>` | Omit `this` parameter from function |
176
157
 
177
- ### Key Types
158
+ ### Template Literal Utilities *(v1.1.0)*
178
159
 
179
160
  | Type | Description |
180
161
  |------|-------------|
181
- | `RequiredKeys<T>` | Get all required property keys |
182
- | `OptionalKeys<T>` | Get all optional property keys |
183
- | `WritableKeys<T>` | Get all writable (non-readonly) keys |
184
- | `ReadonlyKeys<T>` | Get all readonly keys |
162
+ | `ReplaceAll<S, From, To>` | Replace all occurrences |
163
+ | `Replace<S, From, To>` | Replace first occurrence |
164
+ | `Trim<S>` | Trim whitespace |
165
+ | `StringToArray<S>` | Convert string to array |
166
+ | `CapitalizeAll<S>` | Capitalize all words |
167
+ | `StartsWith<S, P>` | Check if string starts with prefix |
168
+ | `EndsWith<S, P>` | Check if string ends with suffix |
169
+ | `StringLength<S>` | Get string length |
185
170
 
186
- ```typescript
187
- interface User {
188
- name: string
189
- age?: number
190
- readonly id: number
191
- }
171
+ ### Numeric Utilities *(v1.1.0)*
192
172
 
193
- RequiredKeys<User> // 'name'
194
- OptionalKeys<User> // 'age'
195
- WritableKeys<User> // 'name' | 'age'
196
- ReadonlyKeys<User> // 'id'
197
- ```
173
+ | Type | Description |
174
+ |------|-------------|
175
+ | `Inc<N>` | Increment number |
176
+ | `Dec<N>` | Decrement number |
177
+ | `Add<A, B>` | Add two numbers |
178
+ | `Subtract<A, B>` | Subtract two numbers |
179
+ | `GreaterThan<A, B>` | Check if A > B |
180
+ | `LessThan<A, B>` | Check if A < B |
181
+ | `Max<A, B>` | Maximum of two numbers |
182
+ | `Min<A, B>` | Minimum of two numbers |
198
183
 
199
184
  ### Path Types
200
185
 
@@ -202,69 +187,53 @@ ReadonlyKeys<User> // 'id'
202
187
  |------|-------------|
203
188
  | `Paths<T>` | Get all nested property paths |
204
189
  | `PathValue<T, P>` | Get value type at path |
205
- | `SplitPath<S>` | Split path string into array |
206
-
207
- ```typescript
208
- interface Obj {
209
- a: { b: { c: string } }
210
- }
211
-
212
- Paths<Obj> // 'a' | 'a.b' | 'a.b.c'
213
- PathValue<Obj, 'a.b'> // { c: string }
214
- SplitPath<'a.b.c'> // ['a', 'b', 'c']
215
- ```
190
+ | `ValidPath<T, P>` | Check if path is valid |
191
+ | `ArrayPaths<T>` | Get paths including array indices |
192
+ | `LeafPaths<T>` | Get paths to primitive values |
216
193
 
217
- ### Literal Types
194
+ ### Key Utilities *(v1.1.0)*
218
195
 
219
196
  | Type | Description |
220
197
  |------|-------------|
221
- | `Literal` | All literal types union |
222
- | `LiteralString<T>` | Exact string literal |
223
- | `LiteralNumber<T>` | Exact number literal |
224
- | `LiteralBoolean<T>` | Exact boolean literal |
225
-
226
- ```typescript
227
- Literal // string | number | boolean | undefined | null | void | bigint
228
- LiteralString<'hello'> // 'hello'
229
- LiteralNumber<42> // 42
230
- LiteralBoolean<true> // true
231
- ```
198
+ | `Keys<T>` | Get all keys |
199
+ | `RenameKeys<T, M>` | Rename keys based on mapping |
200
+ | `PrefixKeys<T, P>` | Add prefix to all keys |
201
+ | `SuffixKeys<T, S>` | Add suffix to all keys |
202
+ | `KeysByValueType<T, V>` | Get keys by value type |
232
203
 
233
- ### String Case Conversion
204
+ ### Record Utilities *(v1.1.0)*
234
205
 
235
206
  | Type | Description |
236
207
  |------|-------------|
237
- | `CamelCase<S>` | Convert to camelCase |
238
- | `SnakeCase<S>` | Convert to snake_case |
239
- | `CamelCaseKeys<T>` | Convert object keys to camelCase |
240
- | `SnakeCaseKeys<T>` | Convert object keys to snake_case |
241
-
242
- ```typescript
243
- CamelCase<'hello_world'> // 'helloWorld'
244
- CamelCase<'foo-bar-baz'> // 'fooBarBaz'
245
- SnakeCase<'helloWorld'> // 'hello_world'
246
- SnakeCase<'XMLParser'> // 'xml_parser'
247
- CamelCaseKeys<{ hello_world: string }> // { helloWorld: string }
248
- ```
249
-
250
- ### Advanced Types
208
+ | `DeepNullable<T>` | Make all properties nullable |
209
+ | `DeepOptional<T>` | Make all properties optional |
210
+ | `Immutable<T>` | Make all properties readonly |
211
+ | `Mutable<T>` | Make all properties mutable |
212
+ | `DeepNonNullable<T>` | Remove null/undefined from all properties |
213
+ | `Exact<T, Shape>` | Ensure exact shape match |
251
214
 
252
- | Type | Description |
253
- |------|-------------|
254
- | `FunctionOnly<T>` | Extract only function properties |
255
- | `DataOnly<T>` | Extract only non-function properties |
256
- | `AtLeastOne<T>` | Require at least one property |
257
- | `StrictExtract<T, U>` | Strictly extract matching types |
258
- | `StrictExclude<T, U>` | Strictly exclude types |
259
- | `UnionToIntersection<U>` | Convert union to intersection |
260
- | `UnionToTuple<T>` | Convert union to tuple |
215
+ ## Examples
261
216
 
262
217
  ```typescript
263
- interface Obj { name: string; onClick: () => void }
264
- FunctionOnly<Obj> // { onClick: () => void }
265
- DataOnly<Obj> // { name: string }
266
-
267
- UnionToIntersection<{ a: string } | { b: number }> // { a: string } & { b: number }
218
+ import type {
219
+ SnakeCase,
220
+ CamelCaseKeys,
221
+ UnionToIntersection,
222
+ AtLeastOne
223
+ } from 'uni-types'
224
+
225
+ // String case conversion
226
+ SnakeCase<'XMLParser'> // 'xml_parser'
227
+ CamelCaseKeys<{ user_name: string, user_age: number }>
228
+ // { userName: string, userAge: number }
229
+
230
+ // Union to intersection
231
+ UnionToIntersection<{ a: string } | { b: number }>
232
+ // { a: string } & { b: number }
233
+
234
+ // Require at least one property
235
+ type Options = AtLeastOne<{ a?: string; b?: number; c?: boolean }>
236
+ // Must have at least one of a, b, or c
268
237
  ```
269
238
 
270
239
  ## Development
@@ -273,32 +242,33 @@ UnionToIntersection<{ a: string } | { b: number }> // { a: string } & { b: numb
273
242
  # Install dependencies
274
243
  pnpm install
275
244
 
276
- # Build
277
- pnpm build
278
-
279
- # Test
245
+ # Run tests
280
246
  pnpm test
281
247
 
282
- # Test with coverage
283
- pnpm test:coverage
248
+ # Build
249
+ pnpm build
284
250
 
285
251
  # Type check
286
252
  pnpm typecheck
287
253
 
288
- # Lint
289
- pnpm lint
254
+ # Start docs dev server
255
+ pnpm docs:dev
290
256
  ```
291
257
 
258
+ ## Contributing
259
+
260
+ Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) for details.
261
+
292
262
  ## License
293
263
 
294
- [MIT](LICENSE)
264
+ [MIT](LICENSE) © [saqqdy](https://github.com/saqqdy)
295
265
 
296
266
  [npm-image]: https://img.shields.io/npm/v/uni-types.svg?style=flat-square
297
267
  [npm-url]: https://npmjs.org/package/uni-types
298
- [typescript-url]: https://badgen.net/badge/icon/typescript?icon=typescript&label
268
+ [typescript-url]: https://img.shields.io/badge/TypeScript-5.x-3178c6?style=flat-square&logo=typescript&logoColor=white
299
269
  [codecov-image]: https://img.shields.io/codecov/c/github/saqqdy/uni-types.svg?style=flat-square
300
- [codecov-url]: https://codecov.io/github/saqqdy/uni-types?branch=master
270
+ [codecov-url]: https://codecov.io/github/saqqdy/uni-types
301
271
  [download-image]: https://img.shields.io/npm/dm/uni-types.svg?style=flat-square
302
272
  [download-url]: https://npmjs.org/package/uni-types
303
- [license-image]: https://img.shields.io/badge/License-MIT-blue.svg
304
- [license-url]: LICENSE
273
+ [license-image]: https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square
274
+ [license-url]: LICENSE