0
# Type Definitions
1
2
Comprehensive TypeScript type utilities and definitions for enhanced type safety and developer experience. These types provide powerful abstractions for building type-safe applications with Solid.js and general TypeScript development.
3
4
## Capabilities
5
6
### Basic Utility Types
7
8
Fundamental type utilities for common programming patterns.
9
10
```typescript { .api }
11
/**
12
* Can be single or in an array
13
*/
14
type Many<T> = T | T[];
15
16
/**
17
* Get the values of an object type
18
*/
19
type Values<O extends Object> = O[keyof O];
20
21
/**
22
* Infers the type of the array elements
23
*/
24
type ItemsOf<T> = T extends (infer E)[] ? E : never;
25
26
/**
27
* Element type of Many<T>
28
*/
29
type ItemsOfMany<T> = T extends any[] ? ItemsOf<T> : T;
30
31
/**
32
* No operation function type
33
*/
34
type Noop = (...a: any[]) => void;
35
```
36
37
**Usage Examples:**
38
39
```typescript
40
import type { Many, Values, ItemsOf, ItemsOfMany } from "@solid-primitives/utils";
41
42
// Many type - accepts single value or array
43
const acceptMany = (input: Many<string>) => {
44
// Handle both "hello" and ["hello", "world"]
45
};
46
47
// Extract array element types
48
type StringArray = string[];
49
type ElementType = ItemsOf<StringArray>; // string
50
51
// Extract values from object
52
type User = { id: number; name: string; active: boolean };
53
type UserValues = Values<User>; // number | string | boolean
54
```
55
56
### Reactive Types
57
58
Types specifically designed for reactive programming and Solid.js integration.
59
60
```typescript { .api }
61
/**
62
* T or a reactive/non-reactive function returning T
63
*/
64
type MaybeAccessor<T> = T | Accessor<T>;
65
66
/**
67
* Accessed value of a MaybeAccessor
68
*/
69
type MaybeAccessorValue<T extends MaybeAccessor<any>> = T extends () => any ? ReturnType<T> : T;
70
71
/**
72
* Solid.js Setter parameter type
73
*/
74
type SetterParam<T> = Parameters<Setter<T>>[0];
75
76
/**
77
* Directive type for Solid.js
78
*/
79
type Directive<P = true> = (el: Element, props: Accessor<P>) => void;
80
81
/**
82
* Effect function type for reactive computations
83
*/
84
type OnAccessEffectFunction<S, Prev, Next extends Prev = Prev> = (
85
input: AccessReturnTypes<S>,
86
prevInput: AccessReturnTypes<S>,
87
v: Prev
88
) => Next;
89
90
/**
91
* Return types of accessed values
92
*/
93
type AccessReturnTypes<S> = S extends MaybeAccessor<any>[]
94
? { [I in keyof S]: AccessReturnTypes<S[I]>; }
95
: MaybeAccessorValue<S>;
96
```
97
98
**Usage Examples:**
99
100
```typescript
101
import { createSignal } from "solid-js";
102
import type { MaybeAccessor, MaybeAccessorValue, Directive } from "@solid-primitives/utils";
103
104
// Function that accepts either value or accessor
105
const processValue = <T>(input: MaybeAccessor<T>): MaybeAccessorValue<T> => {
106
return typeof input === "function" ? input() : input;
107
};
108
109
// Custom directive type
110
const clickOutside: Directive<() => void> = (el, accessor) => {
111
const handler = (e: Event) => {
112
if (!el.contains(e.target as Node)) {
113
accessor()();
114
}
115
};
116
document.addEventListener("click", handler);
117
// ... cleanup logic
118
};
119
```
120
121
### Object Manipulation Types
122
123
Types for safe object manipulation and property access.
124
125
```typescript { .api }
126
/**
127
* Allows to make shallow overwrites to an interface
128
*/
129
type Modify<T, R> = Omit<T, keyof R> & R;
130
131
/**
132
* Allows to make nested overwrites to an interface
133
*/
134
type ModifyDeep<A extends AnyObject, B extends DeepPartialAny<A>> = {
135
[K in keyof A]: B[K] extends never
136
? A[K]
137
: B[K] extends AnyObject
138
? ModifyDeep<A[K], B[K]>
139
: B[K];
140
} & (A extends AnyObject ? Omit<B, keyof A> : A);
141
142
/**
143
* Makes each property optional and turns each leaf property into any, allowing for type overrides
144
*/
145
type DeepPartialAny<T> = {
146
[P in keyof T]?: T[P] extends AnyObject ? DeepPartialAny<T[P]> : any;
147
};
148
149
/**
150
* Get the required keys of an object
151
*/
152
type RequiredKeys<T> = keyof {
153
[K in keyof T as T extends { [_ in K]: unknown } ? K : never]: 0;
154
};
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
import type { Modify, ModifyDeep, RequiredKeys } from "@solid-primitives/utils";
161
162
// Modify interface
163
interface User {
164
id: number;
165
name: string;
166
email: string;
167
}
168
169
type AdminUser = Modify<User, { role: "admin"; permissions: string[] }>;
170
// Result: { id: number; name: string; email: string; role: "admin"; permissions: string[] }
171
172
// Deep modification
173
interface Config {
174
database: { host: string; port: number; };
175
api: { timeout: number; retries: number; };
176
}
177
178
type CustomConfig = ModifyDeep<Config, {
179
database: { ssl: boolean; };
180
api: { version: string; };
181
}>;
182
183
// Required keys extraction
184
interface PartialUser {
185
id: number;
186
name?: string;
187
email?: string;
188
}
189
190
type Required = RequiredKeys<PartialUser>; // "id"
191
```
192
193
### Advanced Utility Types
194
195
Advanced type manipulation utilities for complex scenarios.
196
197
```typescript { .api }
198
/**
199
* Remove the first item of a tuple [1, 2, 3, 4] => [2, 3, 4]
200
*/
201
type Tail<T extends any[]> = ((...t: T) => void) extends (x: any, ...u: infer U) => void ? U : never;
202
203
/**
204
* Convert union to intersection: A | B => A & B
205
*/
206
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
207
208
/**
209
* Extract if possible, otherwise return U
210
*/
211
type ExtractIfPossible<T, U> = Extract<T, U> extends never ? U : Extract<T, U>;
212
213
/**
214
* Removes the [Symbol.iterator] functionality
215
*/
216
type NonIterable<T> = T & { [Symbol.iterator]: never };
217
218
/**
219
* Magic type that prevents inference at usage sites
220
*/
221
type NoInfer<T> = [T][T extends any ? 0 : never];
222
```
223
224
**Usage Examples:**
225
226
```typescript
227
import type { Tail, UnionToIntersection, NoInfer } from "@solid-primitives/utils";
228
229
// Remove first element from tuple
230
type OriginalTuple = [string, number, boolean];
231
type RestTuple = Tail<OriginalTuple>; // [number, boolean]
232
233
// Convert union to intersection
234
type Union = { a: string } | { b: number };
235
type Intersection = UnionToIntersection<Union>; // { a: string } & { b: number }
236
237
// Prevent type inference
238
const createWithDefault = <T>(value: T, defaultValue: NoInfer<T>): T => {
239
return value ?? defaultValue;
240
};
241
```
242
243
### Value and Primitive Types
244
245
Types for working with different categories of values.
246
247
```typescript { .api }
248
/**
249
* Basic object types
250
*/
251
type AnyObject = Record<PropertyKey, any>;
252
type AnyStatic = [] | any[] | AnyObject;
253
type AnyFunction = (...args: any[]) => any;
254
type AnyClass = abstract new (...args: any) => any;
255
256
/**
257
* Primitive value types
258
*/
259
type PrimitiveValue = PropertyKey | boolean | bigint | null | undefined;
260
261
/**
262
* Falsy and truthy types
263
*/
264
type FalsyValue = false | 0 | "" | null | undefined;
265
type Truthy<T> = Exclude<T, FalsyValue>;
266
type Falsy<T> = Extract<T, FalsyValue>;
267
```
268
269
**Usage Examples:**
270
271
```typescript
272
import type { AnyObject, PrimitiveValue, Truthy, Falsy } from "@solid-primitives/utils";
273
274
// Generic object handling
275
const processObject = (obj: AnyObject) => {
276
// Handle any object type safely
277
};
278
279
// Filter truthy/falsy values
280
type MixedArray = (string | null | number | undefined | boolean)[];
281
type TruthyValues = Truthy<MixedArray[number]>; // string | number | true
282
type FalsyValues = Falsy<MixedArray[number]>; // null | undefined | false
283
```
284
285
### Geometric and UI Types
286
287
Types for representing geometric and user interface concepts.
288
289
```typescript { .api }
290
/**
291
* 2D position coordinates
292
*/
293
type Position = {
294
x: number;
295
y: number;
296
};
297
298
/**
299
* Rectangular dimensions
300
*/
301
type Size = {
302
width: number;
303
height: number;
304
};
305
```
306
307
**Usage Examples:**
308
309
```typescript
310
import type { Position, Size } from "@solid-primitives/utils";
311
312
// Mouse position tracking
313
const [mousePos, setMousePos] = createSignal<Position>({ x: 0, y: 0 });
314
315
// Element dimensions
316
const [elementSize, setElementSize] = createSignal<Size>({ width: 0, height: 0 });
317
318
// Combined for element bounds
319
type Bounds = Position & Size;
320
const elementBounds: Bounds = {
321
x: 10,
322
y: 20,
323
width: 100,
324
height: 50
325
};
326
```
327
328
### Type Simplification
329
330
Types for improving type readability and unwrapping complex types.
331
332
```typescript { .api }
333
/**
334
* Unwraps the type definition of an object, making it more readable
335
*/
336
type Simplify<T> = T extends object ? { [K in keyof T]: T[K] } : T;
337
338
/**
339
* Unboxes type definition, making it more readable
340
*/
341
type UnboxLazy<T> = T extends () => infer U ? U : T;
342
343
/**
344
* Narrow type for better inference
345
*/
346
type Narrow<T> = T extends [] ? T : RawNarrow<T>;
347
348
type RawNarrow<T> =
349
| (T extends [] ? [] : never)
350
| (T extends string | number | bigint | boolean ? T : never)
351
| { [K in keyof T]: T[K] extends Function ? T[K] : RawNarrow<T[K]> };
352
```
353
354
**Usage Examples:**
355
356
```typescript
357
import type { Simplify, UnboxLazy, Narrow } from "@solid-primitives/utils";
358
359
// Simplify complex intersection types
360
type ComplexType = { a: string } & { b: number } & { c: boolean };
361
type SimpleType = Simplify<ComplexType>; // { a: string; b: number; c: boolean; }
362
363
// Unbox lazy types
364
type LazyString = () => string;
365
type UnboxedString = UnboxLazy<LazyString>; // string
366
367
// Better type narrowing
368
const narrowed = <T>(value: T): Narrow<T> => value as any;
369
const result = narrowed({ a: 1, b: "hello" }); // Properly narrowed type
370
```
371
372
## Re-exported Types
373
374
The package also re-exports some useful types from Solid.js:
375
376
```typescript { .api }
377
// From solid-js
378
type EffectOptions = import("solid-js").EffectOptions;
379
type OnOptions = import("solid-js").OnOptions;
380
381
// Deprecated - from solid-js/types/reactive/signal.js
382
type ResolvedJSXElement = import("solid-js/types/reactive/signal.js").ResolvedJSXElement;
383
type ResolvedChildren = import("solid-js/types/reactive/signal.js").ResolvedChildren;
384
```
385
386
## External Types (from solid-js)
387
388
Types from Solid.js that are referenced throughout the API:
389
390
```typescript { .api }
391
/**
392
* Solid.js reactive accessor function
393
*/
394
type Accessor<T> = () => T;
395
396
/**
397
* Solid.js reactive setter function
398
*/
399
type Setter<T> = (value: T | ((prev: T) => T)) => T;
400
401
/**
402
* Options for createSignal
403
*/
404
interface SignalOptions<T> {
405
equals?: false | ((prev: T, next: T) => boolean);
406
internal?: boolean;
407
}
408
409
/**
410
* Array of accessor functions
411
*/
412
type AccessorArray<T> = readonly Accessor<T>[];
413
414
/**
415
* Effect function type
416
*/
417
type EffectFunction<Prev, Next = Prev> = (v: Prev) => Next;
418
419
/**
420
* Function that returns void
421
*/
422
type VoidFunction = () => void;
423
```