0
# Type Checkers
1
2
Conditional types for runtime type validation and compile-time type detection. These utilities help you validate and work with type characteristics at both compile time and runtime.
3
4
## Capabilities
5
6
### Exact
7
8
Returns `Type` when type `Type` and `Shape` are identical. Otherwise returns `never`.
9
10
```typescript { .api }
11
type Exact<Type, Shape> = [Type] extends [Shape]
12
? [Shape] extends [Type]
13
? Type
14
: never
15
: never;
16
```
17
18
**Usage Example:**
19
20
```typescript
21
import type { Exact } from "ts-essentials";
22
23
type User = { id: number; name: string; };
24
type UserShape = { id: number; name: string; };
25
type ExtendedUser = { id: number; name: string; email: string; };
26
27
type ExactUser = Exact<User, UserShape>; // User (exact match)
28
type NotExactUser = Exact<User, ExtendedUser>; // never (not exact)
29
30
// Useful for ensuring exact type matches in generics
31
function processExactType<T, U>(
32
value: T,
33
shape: Exact<T, U>
34
): T {
35
return value;
36
}
37
```
38
39
### IsAny
40
41
Returns `true` when type `Type` is `any`. Otherwise returns `false`.
42
43
```typescript { .api }
44
type IsAny<Type> = 0 extends 1 & Type ? true : false;
45
```
46
47
**Usage Example:**
48
49
```typescript
50
import type { IsAny } from "ts-essentials";
51
52
type CheckAny1 = IsAny<any>; // true
53
type CheckAny2 = IsAny<unknown>; // false
54
type CheckAny3 = IsAny<string>; // false
55
type CheckAny4 = IsAny<never>; // false
56
57
// Useful for conditional type logic
58
type SafeType<T> = IsAny<T> extends true ? unknown : T;
59
60
// Runtime usage in type guards
61
function isAnyType<T>(value: T): value is IsAny<T> extends true ? any : never {
62
// Implementation for checking if a value came from an 'any' type
63
return false; // This is conceptual - 'any' detection is compile-time only
64
}
65
```
66
67
### IsNever
68
69
Returns `true` when type `Type` is `never`. Otherwise returns `false`.
70
71
```typescript { .api }
72
type IsNever<Type> = [Type] extends [never] ? true : false;
73
```
74
75
**Usage Example:**
76
77
```typescript
78
import type { IsNever } from "ts-essentials";
79
80
type CheckNever1 = IsNever<never>; // true
81
type CheckNever2 = IsNever<any>; // false
82
type CheckNever3 = IsNever<unknown>; // false
83
type CheckNever4 = IsNever<string>; // false
84
85
// Useful for filtering out never types
86
type FilterNever<T> = IsNever<T> extends true ? never : T;
87
88
type Union = string | never | number;
89
type Filtered = FilterNever<Union>; // string | number
90
91
// Conditional logic based on never detection
92
type ProcessType<T> = IsNever<T> extends true
93
? "No valid type"
94
: `Processing: ${T extends string ? T : "unknown"}`;
95
```
96
97
### IsUnknown
98
99
Returns `true` when type `Type` is `unknown`. Otherwise returns `false`.
100
101
```typescript { .api }
102
type IsUnknown<Type> = [unknown] extends [Type]
103
? [Type] extends [unknown]
104
? true
105
: false
106
: false;
107
```
108
109
**Usage Example:**
110
111
```typescript
112
import type { IsUnknown } from "ts-essentials";
113
114
type CheckUnknown1 = IsUnknown<unknown>; // true
115
type CheckUnknown2 = IsUnknown<any>; // false
116
type CheckUnknown3 = IsUnknown<string>; // false
117
type CheckUnknown4 = IsUnknown<never>; // false
118
119
// Useful for providing safer defaults
120
type SafeDefault<T> = IsUnknown<T> extends true ? string : T;
121
122
type Example1 = SafeDefault<unknown>; // string
123
type Example2 = SafeDefault<number>; // number
124
125
// Type-safe unknown handling
126
type HandleUnknown<T> = IsUnknown<T> extends true
127
? "Please provide a more specific type"
128
: T;
129
```
130
131
### IsTuple
132
133
Returns `Type` when type `Type` is tuple. Otherwise returns `never`.
134
135
```typescript { .api }
136
type IsTuple<Type> = Type extends ReadonlyArray<any>
137
? number extends Type['length']
138
? never
139
: Type
140
: never;
141
```
142
143
**Usage Example:**
144
145
```typescript
146
import type { IsTuple } from "ts-essentials";
147
148
type CheckTuple1 = IsTuple<[string, number]>; // [string, number]
149
type CheckTuple2 = IsTuple<readonly [string, number]>; // readonly [string, number]
150
type CheckTuple3 = IsTuple<string[]>; // never
151
type CheckTuple4 = IsTuple<Array<string>>; // never
152
153
// Process only tuple types
154
type ProcessTuple<T> = IsTuple<T> extends never
155
? "Not a tuple"
156
: T;
157
158
type Result1 = ProcessTuple<[1, 2, 3]>; // [1, 2, 3]
159
type Result2 = ProcessTuple<number[]>; // "Not a tuple"
160
161
// Tuple-specific operations
162
type TupleLength<T> = IsTuple<T> extends never ? never : T['length'];
163
type Len1 = TupleLength<[1, 2, 3]>; // 3
164
type Len2 = TupleLength<string[]>; // never
165
```
166
167
### NonEmptyObject
168
169
Returns `Object` when `Object` has at least one key. Otherwise returns `never`.
170
171
```typescript { .api }
172
type NonEmptyObject<Object extends AnyRecord> = keyof Object extends never ? never : Object;
173
```
174
175
**Usage Example:**
176
177
```typescript
178
import type { NonEmptyObject } from "ts-essentials";
179
180
type CheckObject1 = NonEmptyObject<{ id: number; name: string; }>; // { id: number; name: string; }
181
type CheckObject2 = NonEmptyObject<{}>; // never
182
type CheckObject3 = NonEmptyObject<Record<string, never>>; // never
183
184
// Ensure objects have properties
185
function processNonEmptyObject<T extends Record<string, any>>(
186
obj: NonEmptyObject<T>
187
): NonEmptyObject<T> {
188
return obj;
189
}
190
191
// This works
192
processNonEmptyObject({ id: 1, name: "test" });
193
194
// This would cause a compile error:
195
// processNonEmptyObject({}); // Error: Argument of type '{}' is not assignable
196
197
// Conditional processing based on object emptiness
198
type ProcessObject<T> = NonEmptyObject<T> extends never
199
? "Empty object"
200
: keyof T;
201
202
type Result1 = ProcessObject<{ a: 1; b: 2; }>; // "a" | "b"
203
type Result2 = ProcessObject<{}>; // "Empty object"
204
```
205
206
## Advanced Usage
207
208
Combine type checkers for complex type validation:
209
210
```typescript
211
import type { IsAny, IsNever, IsUnknown, IsTuple, NonEmptyObject } from "ts-essentials";
212
213
// Complex type validation
214
type ValidateType<T> =
215
IsAny<T> extends true ? "Invalid: any type"
216
: IsNever<T> extends true ? "Invalid: never type"
217
: IsUnknown<T> extends true ? "Invalid: unknown type"
218
: T extends object
219
? NonEmptyObject<T> extends never
220
? "Invalid: empty object"
221
: "Valid object type"
222
: T extends ReadonlyArray<any>
223
? IsTuple<T> extends never
224
? "Valid array type"
225
: "Valid tuple type"
226
: "Valid primitive type";
227
228
type Test1 = ValidateType<{ id: number; }>; // "Valid object type"
229
type Test2 = ValidateType<[]>; // "Valid tuple type"
230
type Test3 = ValidateType<string[]>; // "Valid array type"
231
type Test4 = ValidateType<{}>; // "Invalid: empty object"
232
type Test5 = ValidateType<any>; // "Invalid: any type"
233
```
234
235
## Types
236
237
```typescript { .api }
238
type AnyRecord<T = any> = Record<KeyofBase, T>;
239
type KeyofBase = string | number | symbol;
240
```