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 +146 -176
- package/dist/index.d.cts +825 -52
- package/dist/index.d.mts +825 -52
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,46 +1,82 @@
|
|
|
1
|
-
<div
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
3
|
# uni-types
|
|
4
4
|
|
|
5
|
-
Universal TypeScript
|
|
5
|
+
**Universal TypeScript Type Utilities**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
A comprehensive collection of type helpers for TypeScript development
|
|
8
8
|
|
|
9
9
|
[![NPM version][npm-image]][npm-url]
|
|
10
|
-
![
|
|
11
|
-
|
|
12
|
-
[![
|
|
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
|
-
#
|
|
21
|
-
|
|
30
|
+
# pnpm
|
|
31
|
+
pnpm add uni-types
|
|
22
32
|
|
|
23
|
-
#
|
|
24
|
-
|
|
33
|
+
# yarn
|
|
34
|
+
yarn add uni-types
|
|
25
35
|
|
|
26
|
-
#
|
|
27
|
-
|
|
36
|
+
# npm
|
|
37
|
+
npm install uni-types
|
|
28
38
|
```
|
|
29
39
|
|
|
30
|
-
##
|
|
40
|
+
## Quick Start
|
|
31
41
|
|
|
32
42
|
```typescript
|
|
33
|
-
import type {
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
43
|
-
// { name: string; age
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
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
|
-
|
|
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
|
-
| `
|
|
159
|
-
| `
|
|
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
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
###
|
|
158
|
+
### Template Literal Utilities *(v1.1.0)*
|
|
178
159
|
|
|
179
160
|
| Type | Description |
|
|
180
161
|
|------|-------------|
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
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
|
-
|
|
187
|
-
interface User {
|
|
188
|
-
name: string
|
|
189
|
-
age?: number
|
|
190
|
-
readonly id: number
|
|
191
|
-
}
|
|
171
|
+
### Numeric Utilities *(v1.1.0)*
|
|
192
172
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
| `
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
###
|
|
194
|
+
### Key Utilities *(v1.1.0)*
|
|
218
195
|
|
|
219
196
|
| Type | Description |
|
|
220
197
|
|------|-------------|
|
|
221
|
-
| `
|
|
222
|
-
| `
|
|
223
|
-
| `
|
|
224
|
-
| `
|
|
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
|
-
###
|
|
204
|
+
### Record Utilities *(v1.1.0)*
|
|
234
205
|
|
|
235
206
|
| Type | Description |
|
|
236
207
|
|------|-------------|
|
|
237
|
-
| `
|
|
238
|
-
| `
|
|
239
|
-
| `
|
|
240
|
-
| `
|
|
241
|
-
|
|
242
|
-
|
|
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
|
-
|
|
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
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
#
|
|
277
|
-
pnpm build
|
|
278
|
-
|
|
279
|
-
# Test
|
|
245
|
+
# Run tests
|
|
280
246
|
pnpm test
|
|
281
247
|
|
|
282
|
-
#
|
|
283
|
-
pnpm
|
|
248
|
+
# Build
|
|
249
|
+
pnpm build
|
|
284
250
|
|
|
285
251
|
# Type check
|
|
286
252
|
pnpm typecheck
|
|
287
253
|
|
|
288
|
-
#
|
|
289
|
-
pnpm
|
|
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://
|
|
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
|
|
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
|