@xsai/stream-object 0.4.0-beta.9 → 0.4.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/dist/index.d.ts +367 -237
- package/dist/index.js +8 -8
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,175 @@
|
|
|
1
1
|
import { StreamTextOptions, StreamTextResult } from '@xsai/stream-text';
|
|
2
|
-
import { Schema
|
|
2
|
+
import { Schema } from 'xsschema';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
|
|
6
|
+
|
|
7
|
+
@category Type
|
|
8
|
+
*/
|
|
9
|
+
type Primitive =
|
|
10
|
+
| null
|
|
11
|
+
| undefined
|
|
12
|
+
| string
|
|
13
|
+
| number
|
|
14
|
+
| boolean
|
|
15
|
+
| symbol
|
|
16
|
+
| bigint;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
Returns a boolean for whether the given type is `any`.
|
|
20
|
+
|
|
21
|
+
@link https://stackoverflow.com/a/49928360/1490091
|
|
22
|
+
|
|
23
|
+
Useful in type utilities, such as disallowing `any`s to be passed to a function.
|
|
24
|
+
|
|
25
|
+
@example
|
|
26
|
+
```
|
|
27
|
+
import type {IsAny} from 'type-fest';
|
|
28
|
+
|
|
29
|
+
const typedObject = {a: 1, b: 2} as const;
|
|
30
|
+
const anyObject: any = {a: 1, b: 2};
|
|
31
|
+
|
|
32
|
+
function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(object: O, key: K) {
|
|
33
|
+
return object[key];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const typedA = get(typedObject, 'a');
|
|
37
|
+
//=> 1
|
|
38
|
+
|
|
39
|
+
const anyA = get(anyObject, 'a');
|
|
40
|
+
//=> any
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
@category Type Guard
|
|
44
|
+
@category Utilities
|
|
45
|
+
*/
|
|
46
|
+
type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
Returns a boolean for whether the given key is an optional key of type.
|
|
50
|
+
|
|
51
|
+
This is useful when writing utility types or schema validators that need to differentiate `optional` keys.
|
|
52
|
+
|
|
53
|
+
@example
|
|
54
|
+
```
|
|
55
|
+
import type {IsOptionalKeyOf} from 'type-fest';
|
|
56
|
+
|
|
57
|
+
type User = {
|
|
58
|
+
name: string;
|
|
59
|
+
surname: string;
|
|
60
|
+
|
|
61
|
+
luckyNumber?: number;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
type Admin = {
|
|
65
|
+
name: string;
|
|
66
|
+
surname?: string;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
type T1 = IsOptionalKeyOf<User, 'luckyNumber'>;
|
|
70
|
+
//=> true
|
|
71
|
+
|
|
72
|
+
type T2 = IsOptionalKeyOf<User, 'name'>;
|
|
73
|
+
//=> false
|
|
74
|
+
|
|
75
|
+
type T3 = IsOptionalKeyOf<User, 'name' | 'luckyNumber'>;
|
|
76
|
+
//=> boolean
|
|
77
|
+
|
|
78
|
+
type T4 = IsOptionalKeyOf<User | Admin, 'name'>;
|
|
79
|
+
//=> false
|
|
80
|
+
|
|
81
|
+
type T5 = IsOptionalKeyOf<User | Admin, 'surname'>;
|
|
82
|
+
//=> boolean
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
@category Type Guard
|
|
86
|
+
@category Utilities
|
|
87
|
+
*/
|
|
88
|
+
type IsOptionalKeyOf<Type extends object, Key extends keyof Type> =
|
|
89
|
+
IsAny<Type | Key> extends true ? never
|
|
90
|
+
: Key extends keyof Type
|
|
91
|
+
? Type extends Record<Key, Type[Key]>
|
|
92
|
+
? false
|
|
93
|
+
: true
|
|
94
|
+
: false;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
Extract all optional keys from the given type.
|
|
98
|
+
|
|
99
|
+
This is useful when you want to create a new type that contains different type values for the optional keys only.
|
|
100
|
+
|
|
101
|
+
@example
|
|
102
|
+
```
|
|
103
|
+
import type {OptionalKeysOf, Except} from 'type-fest';
|
|
104
|
+
|
|
105
|
+
type User = {
|
|
106
|
+
name: string;
|
|
107
|
+
surname: string;
|
|
108
|
+
|
|
109
|
+
luckyNumber?: number;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const REMOVE_FIELD = Symbol('remove field symbol');
|
|
113
|
+
type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
|
|
114
|
+
[Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const update1: UpdateOperation<User> = {
|
|
118
|
+
name: 'Alice',
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const update2: UpdateOperation<User> = {
|
|
122
|
+
name: 'Bob',
|
|
123
|
+
luckyNumber: REMOVE_FIELD,
|
|
124
|
+
};
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
@category Utilities
|
|
128
|
+
*/
|
|
129
|
+
type OptionalKeysOf<Type extends object> =
|
|
130
|
+
Type extends unknown // For distributing `Type`
|
|
131
|
+
? (keyof {[Key in keyof Type as
|
|
132
|
+
IsOptionalKeyOf<Type, Key> extends false
|
|
133
|
+
? never
|
|
134
|
+
: Key
|
|
135
|
+
]: never
|
|
136
|
+
}) & keyof Type // Intersect with `keyof Type` to ensure result of `OptionalKeysOf<Type>` is always assignable to `keyof Type`
|
|
137
|
+
: never; // Should never happen
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
Extract all required keys from the given type.
|
|
141
|
+
|
|
142
|
+
This is useful when you want to create a new type that contains different type values for the required keys only or use the list of keys for validation purposes, etc...
|
|
143
|
+
|
|
144
|
+
@example
|
|
145
|
+
```
|
|
146
|
+
import type {RequiredKeysOf} from 'type-fest';
|
|
147
|
+
|
|
148
|
+
declare function createValidation<
|
|
149
|
+
Entity extends object,
|
|
150
|
+
Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>,
|
|
151
|
+
>(field: Key, validator: (value: Entity[Key]) => boolean): (entity: Entity) => boolean;
|
|
152
|
+
|
|
153
|
+
type User = {
|
|
154
|
+
name: string;
|
|
155
|
+
surname: string;
|
|
156
|
+
luckyNumber?: number;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const validator1 = createValidation<User>('name', value => value.length < 25);
|
|
160
|
+
const validator2 = createValidation<User>('surname', value => value.length < 25);
|
|
161
|
+
|
|
162
|
+
// @ts-expect-error
|
|
163
|
+
const validator3 = createValidation<User>('luckyNumber', value => value > 0);
|
|
164
|
+
// Error: Argument of type '"luckyNumber"' is not assignable to parameter of type '"name" | "surname"'.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
@category Utilities
|
|
168
|
+
*/
|
|
169
|
+
type RequiredKeysOf<Type extends object> =
|
|
170
|
+
Type extends unknown // For distributing `Type`
|
|
171
|
+
? Exclude<keyof Type, OptionalKeysOf<Type>>
|
|
172
|
+
: never; // Should never happen
|
|
3
173
|
|
|
4
174
|
/**
|
|
5
175
|
Returns a boolean for whether the given type is `never`.
|
|
@@ -14,29 +184,41 @@ Useful in type utilities, such as checking if something does not occur.
|
|
|
14
184
|
```
|
|
15
185
|
import type {IsNever, And} from 'type-fest';
|
|
16
186
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
And<
|
|
20
|
-
IsNever<Exclude<A, B>> extends true ? true : false,
|
|
21
|
-
IsNever<Exclude<B, A>> extends true ? true : false
|
|
22
|
-
>;
|
|
187
|
+
type A = IsNever<never>;
|
|
188
|
+
//=> true
|
|
23
189
|
|
|
24
|
-
type
|
|
25
|
-
|
|
26
|
-
? never
|
|
27
|
-
: void;
|
|
190
|
+
type B = IsNever<any>;
|
|
191
|
+
//=> false
|
|
28
192
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
process.exit(0);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
193
|
+
type C = IsNever<unknown>;
|
|
194
|
+
//=> false
|
|
34
195
|
|
|
35
|
-
|
|
36
|
-
//=>
|
|
196
|
+
type D = IsNever<never[]>;
|
|
197
|
+
//=> false
|
|
37
198
|
|
|
38
|
-
|
|
39
|
-
//=>
|
|
199
|
+
type E = IsNever<object>;
|
|
200
|
+
//=> false
|
|
201
|
+
|
|
202
|
+
type F = IsNever<string>;
|
|
203
|
+
//=> false
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
@example
|
|
207
|
+
```
|
|
208
|
+
import type {IsNever} from 'type-fest';
|
|
209
|
+
|
|
210
|
+
type IsTrue<T> = T extends true ? true : false;
|
|
211
|
+
|
|
212
|
+
// When a distributive conditional is instantiated with `never`, the entire conditional results in `never`.
|
|
213
|
+
type A = IsTrue<never>;
|
|
214
|
+
// ^? type A = never
|
|
215
|
+
|
|
216
|
+
// If you don't want that behaviour, you can explicitly add an `IsNever` check before the distributive conditional.
|
|
217
|
+
type IsTrueFixed<T> =
|
|
218
|
+
IsNever<T> extends true ? false : T extends true ? true : false;
|
|
219
|
+
|
|
220
|
+
type B = IsTrueFixed<never>;
|
|
221
|
+
// ^? type B = false
|
|
40
222
|
```
|
|
41
223
|
|
|
42
224
|
@category Type Guard
|
|
@@ -45,75 +227,125 @@ endIfEqual('abc', '123');
|
|
|
45
227
|
type IsNever<T> = [T] extends [never] ? true : false;
|
|
46
228
|
|
|
47
229
|
/**
|
|
48
|
-
An if-else-like type that resolves depending on whether the given type is `
|
|
230
|
+
An if-else-like type that resolves depending on whether the given `boolean` type is `true` or `false`.
|
|
231
|
+
|
|
232
|
+
Use-cases:
|
|
233
|
+
- You can use this in combination with `Is*` types to create an if-else-like experience. For example, `If<IsAny<any>, 'is any', 'not any'>`.
|
|
49
234
|
|
|
50
|
-
|
|
235
|
+
Note:
|
|
236
|
+
- Returns a union of if branch and else branch if the given type is `boolean` or `any`. For example, `If<boolean, 'Y', 'N'>` will return `'Y' | 'N'`.
|
|
237
|
+
- Returns the else branch if the given type is `never`. For example, `If<never, 'Y', 'N'>` will return `'N'`.
|
|
51
238
|
|
|
52
239
|
@example
|
|
53
240
|
```
|
|
54
|
-
import type {
|
|
241
|
+
import type {If} from 'type-fest';
|
|
55
242
|
|
|
56
|
-
type
|
|
57
|
-
//=>
|
|
243
|
+
type A = If<true, 'yes', 'no'>;
|
|
244
|
+
//=> 'yes'
|
|
245
|
+
|
|
246
|
+
type B = If<false, 'yes', 'no'>;
|
|
247
|
+
//=> 'no'
|
|
248
|
+
|
|
249
|
+
type C = If<boolean, 'yes', 'no'>;
|
|
250
|
+
//=> 'yes' | 'no'
|
|
58
251
|
|
|
59
|
-
type
|
|
60
|
-
//=> '
|
|
252
|
+
type D = If<any, 'yes', 'no'>;
|
|
253
|
+
//=> 'yes' | 'no'
|
|
254
|
+
|
|
255
|
+
type E = If<never, 'yes', 'no'>;
|
|
256
|
+
//=> 'no'
|
|
61
257
|
```
|
|
62
258
|
|
|
63
|
-
@
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
type IfNever<T, TypeIfNever = true, TypeIfNotNever = false> = (
|
|
67
|
-
IsNever<T> extends true ? TypeIfNever : TypeIfNotNever
|
|
68
|
-
);
|
|
259
|
+
@example
|
|
260
|
+
```
|
|
261
|
+
import type {If, IsAny, IsNever} from 'type-fest';
|
|
69
262
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
type NoInfer<T> = T extends infer U ? U : never;
|
|
263
|
+
type A = If<IsAny<unknown>, 'is any', 'not any'>;
|
|
264
|
+
//=> 'not any'
|
|
73
265
|
|
|
74
|
-
|
|
75
|
-
|
|
266
|
+
type B = If<IsNever<never>, 'is never', 'not never'>;
|
|
267
|
+
//=> 'is never'
|
|
268
|
+
```
|
|
76
269
|
|
|
77
|
-
@
|
|
270
|
+
@example
|
|
271
|
+
```
|
|
272
|
+
import type {If, IsEqual} from 'type-fest';
|
|
78
273
|
|
|
79
|
-
|
|
274
|
+
type IfEqual<T, U, IfBranch, ElseBranch> = If<IsEqual<T, U>, IfBranch, ElseBranch>;
|
|
275
|
+
|
|
276
|
+
type A = IfEqual<string, string, 'equal', 'not equal'>;
|
|
277
|
+
//=> 'equal'
|
|
278
|
+
|
|
279
|
+
type B = IfEqual<string, number, 'equal', 'not equal'>;
|
|
280
|
+
//=> 'not equal'
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Note: Sometimes using the `If` type can make an implementation non–tail-recursive, which can impact performance. In such cases, it’s better to use a conditional directly. Refer to the following example:
|
|
80
284
|
|
|
81
285
|
@example
|
|
82
286
|
```
|
|
83
|
-
import type {
|
|
287
|
+
import type {If, IsEqual, StringRepeat} from 'type-fest';
|
|
84
288
|
|
|
85
|
-
|
|
86
|
-
const anyObject: any = {a: 1, b: 2};
|
|
289
|
+
type HundredZeroes = StringRepeat<'0', 100>;
|
|
87
290
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
291
|
+
// The following implementation is not tail recursive
|
|
292
|
+
type Includes<S extends string, Char extends string> =
|
|
293
|
+
S extends `${infer First}${infer Rest}`
|
|
294
|
+
? If<IsEqual<First, Char>,
|
|
295
|
+
'found',
|
|
296
|
+
Includes<Rest, Char>>
|
|
297
|
+
: 'not found';
|
|
91
298
|
|
|
92
|
-
|
|
93
|
-
|
|
299
|
+
// Hence, instantiations with long strings will fail
|
|
300
|
+
// @ts-expect-error
|
|
301
|
+
type Fails = Includes<HundredZeroes, '1'>;
|
|
302
|
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
303
|
+
// Error: Type instantiation is excessively deep and possibly infinite.
|
|
94
304
|
|
|
95
|
-
|
|
96
|
-
|
|
305
|
+
// However, if we use a simple conditional instead of `If`, the implementation becomes tail-recursive
|
|
306
|
+
type IncludesWithoutIf<S extends string, Char extends string> =
|
|
307
|
+
S extends `${infer First}${infer Rest}`
|
|
308
|
+
? IsEqual<First, Char> extends true
|
|
309
|
+
? 'found'
|
|
310
|
+
: IncludesWithoutIf<Rest, Char>
|
|
311
|
+
: 'not found';
|
|
312
|
+
|
|
313
|
+
// Now, instantiations with long strings will work
|
|
314
|
+
type Works = IncludesWithoutIf<HundredZeroes, '1'>;
|
|
315
|
+
//=> 'not found'
|
|
97
316
|
```
|
|
98
317
|
|
|
99
318
|
@category Type Guard
|
|
100
319
|
@category Utilities
|
|
101
320
|
*/
|
|
102
|
-
type
|
|
321
|
+
type If<Type extends boolean, IfBranch, ElseBranch> =
|
|
322
|
+
IsNever<Type> extends true
|
|
323
|
+
? ElseBranch
|
|
324
|
+
: Type extends true
|
|
325
|
+
? IfBranch
|
|
326
|
+
: ElseBranch;
|
|
103
327
|
|
|
104
328
|
/**
|
|
105
|
-
Matches any
|
|
329
|
+
Matches any primitive, `void`, `Date`, or `RegExp` value.
|
|
330
|
+
*/
|
|
331
|
+
type BuiltIns = Primitive | void | Date | RegExp;
|
|
106
332
|
|
|
107
|
-
|
|
333
|
+
/**
|
|
334
|
+
Test if the given function has multiple call signatures.
|
|
335
|
+
|
|
336
|
+
Needed to handle the case of a single call signature with properties.
|
|
337
|
+
|
|
338
|
+
Multiple call signatures cannot currently be supported due to a TypeScript limitation.
|
|
339
|
+
@see https://github.com/microsoft/TypeScript/issues/29732
|
|
108
340
|
*/
|
|
109
|
-
type
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
341
|
+
type HasMultipleCallSignatures<T extends (...arguments_: any[]) => unknown> =
|
|
342
|
+
T extends {(...arguments_: infer A): unknown; (...arguments_: infer B): unknown}
|
|
343
|
+
? B extends A
|
|
344
|
+
? A extends B
|
|
345
|
+
? false
|
|
346
|
+
: true
|
|
347
|
+
: true
|
|
348
|
+
: false;
|
|
117
349
|
|
|
118
350
|
/**
|
|
119
351
|
Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
|
|
@@ -160,89 +392,21 @@ const literal = {foo: 123, bar: 'hello', baz: 456};
|
|
|
160
392
|
const someType: SomeType = literal;
|
|
161
393
|
const someInterface: SomeInterface = literal;
|
|
162
394
|
|
|
163
|
-
function fn(object: Record<string, unknown>): void
|
|
395
|
+
declare function fn(object: Record<string, unknown>): void;
|
|
164
396
|
|
|
165
397
|
fn(literal); // Good: literal object type is sealed
|
|
166
398
|
fn(someType); // Good: type is sealed
|
|
399
|
+
// @ts-expect-error
|
|
167
400
|
fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
|
|
168
401
|
fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
|
|
169
402
|
```
|
|
170
403
|
|
|
171
404
|
@link https://github.com/microsoft/TypeScript/issues/15300
|
|
172
|
-
@see SimplifyDeep
|
|
405
|
+
@see {@link SimplifyDeep}
|
|
173
406
|
@category Object
|
|
174
407
|
*/
|
|
175
408
|
type Simplify<T> = {[KeyType in keyof T]: T[KeyType]} & {};
|
|
176
409
|
|
|
177
|
-
/**
|
|
178
|
-
Extract all optional keys from the given type.
|
|
179
|
-
|
|
180
|
-
This is useful when you want to create a new type that contains different type values for the optional keys only.
|
|
181
|
-
|
|
182
|
-
@example
|
|
183
|
-
```
|
|
184
|
-
import type {OptionalKeysOf, Except} from 'type-fest';
|
|
185
|
-
|
|
186
|
-
interface User {
|
|
187
|
-
name: string;
|
|
188
|
-
surname: string;
|
|
189
|
-
|
|
190
|
-
luckyNumber?: number;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const REMOVE_FIELD = Symbol('remove field symbol');
|
|
194
|
-
type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
|
|
195
|
-
[Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
const update1: UpdateOperation<User> = {
|
|
199
|
-
name: 'Alice'
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
const update2: UpdateOperation<User> = {
|
|
203
|
-
name: 'Bob',
|
|
204
|
-
luckyNumber: REMOVE_FIELD
|
|
205
|
-
};
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
@category Utilities
|
|
209
|
-
*/
|
|
210
|
-
type OptionalKeysOf<BaseType extends object> =
|
|
211
|
-
BaseType extends unknown // For distributing `BaseType`
|
|
212
|
-
? (keyof {
|
|
213
|
-
[Key in keyof BaseType as BaseType extends Record<Key, BaseType[Key]> ? never : Key]: never
|
|
214
|
-
}) & (keyof BaseType) // Intersect with `keyof BaseType` to ensure result of `OptionalKeysOf<BaseType>` is always assignable to `keyof BaseType`
|
|
215
|
-
: never; // Should never happen
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
Extract all required keys from the given type.
|
|
219
|
-
|
|
220
|
-
This is useful when you want to create a new type that contains different type values for the required keys only or use the list of keys for validation purposes, etc...
|
|
221
|
-
|
|
222
|
-
@example
|
|
223
|
-
```
|
|
224
|
-
import type {RequiredKeysOf} from 'type-fest';
|
|
225
|
-
|
|
226
|
-
declare function createValidation<Entity extends object, Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>>(field: Key, validator: (value: Entity[Key]) => boolean): ValidatorFn;
|
|
227
|
-
|
|
228
|
-
interface User {
|
|
229
|
-
name: string;
|
|
230
|
-
surname: string;
|
|
231
|
-
|
|
232
|
-
luckyNumber?: number;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const validator1 = createValidation<User>('name', value => value.length < 25);
|
|
236
|
-
const validator2 = createValidation<User>('surname', value => value.length < 25);
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
@category Utilities
|
|
240
|
-
*/
|
|
241
|
-
type RequiredKeysOf<BaseType extends object> =
|
|
242
|
-
BaseType extends unknown // For distributing `BaseType`
|
|
243
|
-
? Exclude<keyof BaseType, OptionalKeysOf<BaseType>>
|
|
244
|
-
: never; // Should never happen
|
|
245
|
-
|
|
246
410
|
/**
|
|
247
411
|
Omit any index signatures from the given object type, leaving only explicitly defined properties.
|
|
248
412
|
|
|
@@ -260,6 +424,7 @@ It relies on the fact that an empty object (`{}`) is assignable to an object wit
|
|
|
260
424
|
```
|
|
261
425
|
const indexed: Record<string, unknown> = {}; // Allowed
|
|
262
426
|
|
|
427
|
+
// @ts-expect-error
|
|
263
428
|
const keyed: Record<'foo', unknown> = {}; // Error
|
|
264
429
|
// => TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
|
|
265
430
|
```
|
|
@@ -273,16 +438,14 @@ type Indexed = {} extends Record<string, unknown>
|
|
|
273
438
|
// => '✅ `{}` is assignable to `Record<string, unknown>`'
|
|
274
439
|
|
|
275
440
|
type Keyed = {} extends Record<'foo' | 'bar', unknown>
|
|
276
|
-
?
|
|
277
|
-
:
|
|
441
|
+
? '✅ `{}` is assignable to `Record<\'foo\' | \'bar\', unknown>`'
|
|
442
|
+
: '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`';
|
|
278
443
|
// => "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`"
|
|
279
444
|
```
|
|
280
445
|
|
|
281
446
|
Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
|
|
282
447
|
|
|
283
448
|
```
|
|
284
|
-
import type {OmitIndexSignature} from 'type-fest';
|
|
285
|
-
|
|
286
449
|
type OmitIndexSignature<ObjectType> = {
|
|
287
450
|
[KeyType in keyof ObjectType // Map each key of `ObjectType`...
|
|
288
451
|
]: ObjectType[KeyType]; // ...to its original value, i.e. `OmitIndexSignature<Foo> == Foo`.
|
|
@@ -292,14 +455,12 @@ type OmitIndexSignature<ObjectType> = {
|
|
|
292
455
|
...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
|
|
293
456
|
|
|
294
457
|
```
|
|
295
|
-
import type {OmitIndexSignature} from 'type-fest';
|
|
296
|
-
|
|
297
458
|
type OmitIndexSignature<ObjectType> = {
|
|
298
459
|
[KeyType in keyof ObjectType
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
460
|
+
// Is `{}` assignable to `Record<KeyType, unknown>`?
|
|
461
|
+
as {} extends Record<KeyType, unknown>
|
|
462
|
+
? never // ✅ `{}` is assignable to `Record<KeyType, unknown>`
|
|
463
|
+
: KeyType // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
|
|
303
464
|
]: ObjectType[KeyType];
|
|
304
465
|
};
|
|
305
466
|
```
|
|
@@ -310,27 +471,27 @@ If `{}` is assignable, it means that `KeyType` is an index signature and we want
|
|
|
310
471
|
```
|
|
311
472
|
import type {OmitIndexSignature} from 'type-fest';
|
|
312
473
|
|
|
313
|
-
|
|
474
|
+
type Example = {
|
|
314
475
|
// These index signatures will be removed.
|
|
315
|
-
[x: string]: any
|
|
316
|
-
[x: number]: any
|
|
317
|
-
[x: symbol]: any
|
|
318
|
-
[x: `head-${string}`]: string
|
|
319
|
-
[x: `${string}-tail`]: string
|
|
320
|
-
[x: `head-${string}-tail`]: string
|
|
321
|
-
[x: `${bigint}`]: string
|
|
322
|
-
[x: `embedded-${number}`]: string
|
|
476
|
+
[x: string]: any;
|
|
477
|
+
[x: number]: any;
|
|
478
|
+
[x: symbol]: any;
|
|
479
|
+
[x: `head-${string}`]: string;
|
|
480
|
+
[x: `${string}-tail`]: string;
|
|
481
|
+
[x: `head-${string}-tail`]: string;
|
|
482
|
+
[x: `${bigint}`]: string;
|
|
483
|
+
[x: `embedded-${number}`]: string;
|
|
323
484
|
|
|
324
485
|
// These explicitly defined keys will remain.
|
|
325
486
|
foo: 'bar';
|
|
326
487
|
qux?: 'baz';
|
|
327
|
-
}
|
|
488
|
+
};
|
|
328
489
|
|
|
329
490
|
type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
|
|
330
491
|
// => { foo: 'bar'; qux?: 'baz' | undefined; }
|
|
331
492
|
```
|
|
332
493
|
|
|
333
|
-
@see PickIndexSignature
|
|
494
|
+
@see {@link PickIndexSignature}
|
|
334
495
|
@category Object
|
|
335
496
|
*/
|
|
336
497
|
type OmitIndexSignature<ObjectType> = {
|
|
@@ -381,7 +542,7 @@ type ExampleIndexSignature = PickIndexSignature<Example>;
|
|
|
381
542
|
// }
|
|
382
543
|
```
|
|
383
544
|
|
|
384
|
-
@see OmitIndexSignature
|
|
545
|
+
@see {@link OmitIndexSignature}
|
|
385
546
|
@category Object
|
|
386
547
|
*/
|
|
387
548
|
type PickIndexSignature<ObjectType> = {
|
|
@@ -402,12 +563,12 @@ Merge two types into a new type. Keys of the second type overrides keys of the f
|
|
|
402
563
|
```
|
|
403
564
|
import type {Merge} from 'type-fest';
|
|
404
565
|
|
|
405
|
-
|
|
566
|
+
type Foo = {
|
|
406
567
|
[x: string]: unknown;
|
|
407
568
|
[x: number]: unknown;
|
|
408
569
|
foo: string;
|
|
409
570
|
bar: symbol;
|
|
410
|
-
}
|
|
571
|
+
};
|
|
411
572
|
|
|
412
573
|
type Bar = {
|
|
413
574
|
[x: number]: number;
|
|
@@ -431,38 +592,10 @@ export type FooBar = Merge<Foo, Bar>;
|
|
|
431
592
|
*/
|
|
432
593
|
type Merge<Destination, Source> =
|
|
433
594
|
Simplify<
|
|
434
|
-
SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
|
|
435
|
-
& SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>
|
|
595
|
+
SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
|
|
596
|
+
& SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>
|
|
436
597
|
>;
|
|
437
598
|
|
|
438
|
-
/**
|
|
439
|
-
An if-else-like type that resolves depending on whether the given type is `any`.
|
|
440
|
-
|
|
441
|
-
@see {@link IsAny}
|
|
442
|
-
|
|
443
|
-
@example
|
|
444
|
-
```
|
|
445
|
-
import type {IfAny} from 'type-fest';
|
|
446
|
-
|
|
447
|
-
type ShouldBeTrue = IfAny<any>;
|
|
448
|
-
//=> true
|
|
449
|
-
|
|
450
|
-
type ShouldBeBar = IfAny<'not any', 'foo', 'bar'>;
|
|
451
|
-
//=> 'bar'
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
@category Type Guard
|
|
455
|
-
@category Utilities
|
|
456
|
-
*/
|
|
457
|
-
type IfAny<T, TypeIfAny = true, TypeIfNotAny = false> = (
|
|
458
|
-
IsAny<T> extends true ? TypeIfAny : TypeIfNotAny
|
|
459
|
-
);
|
|
460
|
-
|
|
461
|
-
/**
|
|
462
|
-
Matches any primitive, `void`, `Date`, or `RegExp` value.
|
|
463
|
-
*/
|
|
464
|
-
type BuiltIns = Primitive | void | Date | RegExp;
|
|
465
|
-
|
|
466
599
|
/**
|
|
467
600
|
Merges user specified options with default options.
|
|
468
601
|
|
|
@@ -520,18 +653,13 @@ type ApplyDefaultOptions<
|
|
|
520
653
|
Defaults extends Simplify<Omit<Required<Options>, RequiredKeysOf<Options>> & Partial<Record<RequiredKeysOf<Options>, never>>>,
|
|
521
654
|
SpecifiedOptions extends Options,
|
|
522
655
|
> =
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
: never
|
|
531
|
-
: Key
|
|
532
|
-
]: SpecifiedOptions[Key]
|
|
533
|
-
}> & Required<Options>> // `& Required<Options>` ensures that `ApplyDefaultOptions<SomeOption, ...>` is always assignable to `Required<SomeOption>`
|
|
534
|
-
>>;
|
|
656
|
+
If<IsAny<SpecifiedOptions>, Defaults,
|
|
657
|
+
If<IsNever<SpecifiedOptions>, Defaults,
|
|
658
|
+
Simplify<Merge<Defaults, {
|
|
659
|
+
[Key in keyof SpecifiedOptions
|
|
660
|
+
as Key extends OptionalKeysOf<Options> ? undefined extends SpecifiedOptions[Key] ? never : Key : Key
|
|
661
|
+
]: SpecifiedOptions[Key]
|
|
662
|
+
}> & Required<Options>>>>;
|
|
535
663
|
|
|
536
664
|
/**
|
|
537
665
|
@see {@link PartialDeep}
|
|
@@ -550,10 +678,10 @@ type PartialDeepOptions = {
|
|
|
550
678
|
- When set to `true`, elements of non-tuple arrays can be `undefined`.
|
|
551
679
|
- When set to `false`, only explicitly defined elements are allowed in non-tuple arrays, ensuring stricter type checking.
|
|
552
680
|
|
|
553
|
-
@default
|
|
681
|
+
@default false
|
|
554
682
|
|
|
555
683
|
@example
|
|
556
|
-
You can
|
|
684
|
+
You can allow `undefined` values in non-tuple arrays by passing `{recurseIntoArrays: true; allowUndefinedInNonTupleArrays: true}` as the second type argument:
|
|
557
685
|
|
|
558
686
|
```
|
|
559
687
|
import type {PartialDeep} from 'type-fest';
|
|
@@ -562,10 +690,9 @@ type PartialDeepOptions = {
|
|
|
562
690
|
languages: string[];
|
|
563
691
|
};
|
|
564
692
|
|
|
565
|
-
declare const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true; allowUndefinedInNonTupleArrays:
|
|
693
|
+
declare const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true; allowUndefinedInNonTupleArrays: true}>;
|
|
566
694
|
|
|
567
|
-
partialSettings.languages = [undefined]; //
|
|
568
|
-
partialSettings.languages = []; // Ok
|
|
695
|
+
partialSettings.languages = [undefined]; // OK
|
|
569
696
|
```
|
|
570
697
|
*/
|
|
571
698
|
readonly allowUndefinedInNonTupleArrays?: boolean;
|
|
@@ -573,7 +700,7 @@ type PartialDeepOptions = {
|
|
|
573
700
|
|
|
574
701
|
type DefaultPartialDeepOptions = {
|
|
575
702
|
recurseIntoArrays: false;
|
|
576
|
-
allowUndefinedInNonTupleArrays:
|
|
703
|
+
allowUndefinedInNonTupleArrays: false;
|
|
577
704
|
};
|
|
578
705
|
|
|
579
706
|
/**
|
|
@@ -587,19 +714,19 @@ Use-cases:
|
|
|
587
714
|
```
|
|
588
715
|
import type {PartialDeep} from 'type-fest';
|
|
589
716
|
|
|
590
|
-
|
|
717
|
+
let settings = {
|
|
591
718
|
textEditor: {
|
|
592
719
|
fontSize: 14,
|
|
593
720
|
fontColor: '#000000',
|
|
594
|
-
fontWeight: 400
|
|
721
|
+
fontWeight: 400,
|
|
595
722
|
},
|
|
596
723
|
autocomplete: false,
|
|
597
|
-
autosave: true
|
|
724
|
+
autosave: true,
|
|
598
725
|
};
|
|
599
726
|
|
|
600
|
-
const applySavedSettings = (savedSettings: PartialDeep<
|
|
601
|
-
|
|
602
|
-
|
|
727
|
+
const applySavedSettings = (savedSettings: PartialDeep<typeof settings>) => (
|
|
728
|
+
{...settings, ...savedSettings, textEditor: {...settings.textEditor, ...savedSettings.textEditor}}
|
|
729
|
+
);
|
|
603
730
|
|
|
604
731
|
settings = applySavedSettings({textEditor: {fontWeight: 500}});
|
|
605
732
|
```
|
|
@@ -609,13 +736,15 @@ By default, this does not affect elements in array and tuple types. You can chan
|
|
|
609
736
|
```
|
|
610
737
|
import type {PartialDeep} from 'type-fest';
|
|
611
738
|
|
|
612
|
-
type
|
|
613
|
-
|
|
614
|
-
}
|
|
739
|
+
type Shape = {
|
|
740
|
+
dimensions: [number, number];
|
|
741
|
+
};
|
|
615
742
|
|
|
616
|
-
const
|
|
617
|
-
|
|
743
|
+
const partialShape: PartialDeep<Shape, {recurseIntoArrays: true}> = {
|
|
744
|
+
dimensions: [], // OK
|
|
618
745
|
};
|
|
746
|
+
|
|
747
|
+
partialShape.dimensions = [15]; // OK
|
|
619
748
|
```
|
|
620
749
|
|
|
621
750
|
@see {@link PartialDeepOptions}
|
|
@@ -630,16 +759,20 @@ type PartialDeep<T, Options extends PartialDeepOptions = {}> =
|
|
|
630
759
|
|
|
631
760
|
type _PartialDeep<T, Options extends Required<PartialDeepOptions>> = T extends BuiltIns | ((new (...arguments_: any[]) => unknown))
|
|
632
761
|
? T
|
|
633
|
-
:
|
|
634
|
-
?
|
|
635
|
-
: T extends
|
|
636
|
-
?
|
|
637
|
-
: T extends
|
|
638
|
-
?
|
|
639
|
-
: T extends
|
|
640
|
-
?
|
|
641
|
-
: T extends
|
|
642
|
-
?
|
|
762
|
+
: T extends Map<infer KeyType, infer ValueType>
|
|
763
|
+
? PartialMapDeep<KeyType, ValueType, Options>
|
|
764
|
+
: T extends Set<infer ItemType>
|
|
765
|
+
? PartialSetDeep<ItemType, Options>
|
|
766
|
+
: T extends ReadonlyMap<infer KeyType, infer ValueType>
|
|
767
|
+
? PartialReadonlyMapDeep<KeyType, ValueType, Options>
|
|
768
|
+
: T extends ReadonlySet<infer ItemType>
|
|
769
|
+
? PartialReadonlySetDeep<ItemType, Options>
|
|
770
|
+
: T extends (...arguments_: any[]) => unknown
|
|
771
|
+
? IsNever<keyof T> extends true
|
|
772
|
+
? T // For functions with no properties
|
|
773
|
+
: HasMultipleCallSignatures<T> extends true
|
|
774
|
+
? T
|
|
775
|
+
: ((...arguments_: Parameters<T>) => ReturnType<T>) & PartialObjectDeep<T, Options>
|
|
643
776
|
: T extends object
|
|
644
777
|
? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
|
|
645
778
|
? Options['recurseIntoArrays'] extends true
|
|
@@ -675,15 +808,12 @@ type PartialReadonlySetDeep<T, Options extends Required<PartialDeepOptions>> = {
|
|
|
675
808
|
/**
|
|
676
809
|
Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`.
|
|
677
810
|
*/
|
|
678
|
-
type PartialObjectDeep<ObjectType extends object, Options extends Required<PartialDeepOptions>> =
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
: {}) & ({
|
|
682
|
-
[KeyType in keyof ObjectType]?: _PartialDeep<ObjectType[KeyType], Options>
|
|
683
|
-
});
|
|
811
|
+
type PartialObjectDeep<ObjectType extends object, Options extends Required<PartialDeepOptions>> = {
|
|
812
|
+
[KeyType in keyof ObjectType]?: _PartialDeep<ObjectType[KeyType], Options>
|
|
813
|
+
};
|
|
684
814
|
|
|
685
815
|
interface StreamObjectOnFinishResult<T extends Schema> {
|
|
686
|
-
object?:
|
|
816
|
+
object?: Schema.InferOutput<T>;
|
|
687
817
|
}
|
|
688
818
|
interface StreamObjectOptions<T extends Schema> extends StreamTextOptions {
|
|
689
819
|
schema: T;
|
|
@@ -693,24 +823,24 @@ interface StreamObjectOptions<T extends Schema> extends StreamTextOptions {
|
|
|
693
823
|
strict?: boolean;
|
|
694
824
|
}
|
|
695
825
|
interface StreamObjectResult<T extends Schema> extends StreamTextResult {
|
|
696
|
-
elementStream?: ReadableStream<
|
|
697
|
-
partialObjectStream?: ReadableStream<PartialDeep<
|
|
826
|
+
elementStream?: ReadableStream<Schema.InferOutput<T>>;
|
|
827
|
+
partialObjectStream?: ReadableStream<PartialDeep<Schema.InferOutput<T>>>;
|
|
698
828
|
}
|
|
699
829
|
declare function streamObject<T extends Schema>(options: StreamObjectOptions<T> & {
|
|
700
830
|
output: 'array';
|
|
701
831
|
}): Promise<StreamObjectResult<T> & {
|
|
702
|
-
elementStream: ReadableStream<
|
|
832
|
+
elementStream: ReadableStream<Schema.InferOutput<T>>;
|
|
703
833
|
partialObjectStream: undefined;
|
|
704
834
|
}>;
|
|
705
835
|
declare function streamObject<T extends Schema>(options: StreamObjectOptions<T> & {
|
|
706
836
|
output: 'object';
|
|
707
837
|
}): Promise<StreamObjectResult<T> & {
|
|
708
838
|
elementStream: undefined;
|
|
709
|
-
partialObjectStream: ReadableStream<PartialDeep<
|
|
839
|
+
partialObjectStream: ReadableStream<PartialDeep<Schema.InferOutput<T>>>;
|
|
710
840
|
}>;
|
|
711
841
|
declare function streamObject<T extends Schema>(options: StreamObjectOptions<T>): Promise<StreamObjectResult<T> & {
|
|
712
842
|
elementStream: undefined;
|
|
713
|
-
partialObjectStream: ReadableStream<PartialDeep<
|
|
843
|
+
partialObjectStream: ReadableStream<PartialDeep<Schema.InferOutput<T>>>;
|
|
714
844
|
}>;
|
|
715
845
|
|
|
716
846
|
declare const toElementStream: <T>(stream: ReadableStream<string>) => ReadableStream<T>;
|
package/dist/index.js
CHANGED
|
@@ -19,23 +19,23 @@ var hasRequiredParse;
|
|
|
19
19
|
function requireParse () {
|
|
20
20
|
if (hasRequiredParse) return parse;
|
|
21
21
|
hasRequiredParse = 1;
|
|
22
|
-
(function (exports) {
|
|
23
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.parse = exports.enableErrorLogging = exports.disableErrorLogging = exports.setErrorLogger = void 0;
|
|
22
|
+
(function (exports$1) {
|
|
23
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
24
|
+
exports$1.parse = exports$1.enableErrorLogging = exports$1.disableErrorLogging = exports$1.setErrorLogger = void 0;
|
|
25
25
|
let logError = console.error;
|
|
26
26
|
function setErrorLogger(logger) {
|
|
27
27
|
logError = logger;
|
|
28
28
|
}
|
|
29
|
-
exports.setErrorLogger = setErrorLogger;
|
|
29
|
+
exports$1.setErrorLogger = setErrorLogger;
|
|
30
30
|
function disableErrorLogging() {
|
|
31
31
|
logError = () => {
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
-
exports.disableErrorLogging = disableErrorLogging;
|
|
34
|
+
exports$1.disableErrorLogging = disableErrorLogging;
|
|
35
35
|
function enableErrorLogging() {
|
|
36
36
|
logError = console.error;
|
|
37
37
|
}
|
|
38
|
-
exports.enableErrorLogging = enableErrorLogging;
|
|
38
|
+
exports$1.enableErrorLogging = enableErrorLogging;
|
|
39
39
|
function parse(s) {
|
|
40
40
|
if (s === void 0) {
|
|
41
41
|
return void 0;
|
|
@@ -62,7 +62,7 @@ function requireParse () {
|
|
|
62
62
|
return data;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
exports.parse = parse;
|
|
65
|
+
exports$1.parse = parse;
|
|
66
66
|
(function(parse2) {
|
|
67
67
|
parse2.onExtraToken = (text, data, reminding) => {
|
|
68
68
|
logError("parsed json with extra tokens:", {
|
|
@@ -71,7 +71,7 @@ function requireParse () {
|
|
|
71
71
|
reminding
|
|
72
72
|
});
|
|
73
73
|
};
|
|
74
|
-
})(parse = exports.parse || (exports.parse = {}));
|
|
74
|
+
})(parse = exports$1.parse || (exports$1.parse = {}));
|
|
75
75
|
function parseAny(s, e, fallback) {
|
|
76
76
|
const parser = parsers[s[0]] || fallback;
|
|
77
77
|
if (!parser) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsai/stream-object",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.4.0
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"description": "extra-small AI SDK.",
|
|
6
6
|
"author": "Moeru AI",
|
|
7
7
|
"license": "MIT",
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@xsai/stream-text": "~0.4.0
|
|
33
|
-
"xsschema": "~0.4.0
|
|
32
|
+
"@xsai/stream-text": "~0.4.0",
|
|
33
|
+
"xsschema": "~0.4.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@valibot/to-json-schema": "^1.0.0",
|
|
37
|
-
"best-effort-json-parser": "^1.1
|
|
38
|
-
"type-fest": "^
|
|
37
|
+
"best-effort-json-parser": "^1.2.1",
|
|
38
|
+
"type-fest": "^5.3.1",
|
|
39
39
|
"valibot": "^1.0.0"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|