or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-types.mdarray-types.mdbasic-types.mdbuiltin-types.mdgeneric-utils.mdindex.mdnumber-validation.mdobject-types.mdstring-types.md
tile.json

generic-utils.mddocs/

0

# Generic Type Utilities

1

2

Generic type checking utilities including the core type detection function, factory functions for creating custom type guards, and generic instance validation. These are the most flexible and powerful functions in the is-what library.

3

4

## Capabilities

5

6

### Core Type Detection

7

8

Returns the object type of the given payload using `Object.prototype.toString`. This is the foundational utility used by most other functions in the library.

9

10

```typescript { .api }

11

/**

12

* Returns the object type of the given payload

13

* @param payload - Value to inspect

14

* @returns String representation of the object type

15

*/

16

function getType(payload: unknown): string;

17

```

18

19

**Usage Examples:**

20

21

```typescript

22

import { getType } from "is-what";

23

24

// Primitive types

25

getType("hello"); // "String"

26

getType(42); // "Number"

27

getType(true); // "Boolean"

28

getType(null); // "Null"

29

getType(undefined); // "Undefined"

30

getType(Symbol("test")); // "Symbol"

31

getType(123n); // "BigInt"

32

33

// Object types

34

getType({}); // "Object"

35

getType([]); // "Array"

36

getType(new Date()); // "Date"

37

getType(/regex/); // "RegExp"

38

getType(() => {}); // "Function"

39

getType(new Map()); // "Map"

40

getType(new Set()); // "Set"

41

getType(new Error()); // "Error"

42

43

// Custom classes

44

class MyClass {}

45

getType(new MyClass()); // "Object" (custom classes show as Object)

46

47

// Practical usage

48

function createTypeChecker(expectedType: string) {

49

return (value: unknown) => getType(value) === expectedType;

50

}

51

52

const isStringType = createTypeChecker("String");

53

isStringType("hello"); // true

54

isStringType(123); // false

55

56

// Debug utility

57

function debugType(value: unknown, label: string = "value") {

58

console.log(`${label}: ${getType(value)} = ${JSON.stringify(value)}`);

59

}

60

61

debugType("test", "input"); // "input: String = "test""

62

debugType([1, 2, 3], "array"); // "array: Array = [1,2,3]"

63

```

64

65

### Generic Type Validation

66

67

Generic check to verify payload is of a given type. Useful for runtime type checking against constructor functions.

68

69

```typescript { .api }

70

/**

71

* Does a generic check to check that the given payload is of a given type.

72

* In cases like Number, it will return true for NaN as NaN is a Number;

73

* It will, however, differentiate between object and null

74

* @param payload - Value to check

75

* @param type - Constructor function or class to check against

76

* @returns Type guard indicating if payload is of the specified type

77

* @throws {TypeError} Will throw type error if type is an invalid type

78

*/

79

function isType<T extends AnyFunction | AnyClass>(

80

payload: unknown,

81

type: T

82

): payload is T;

83

84

type AnyClass = new (...args: unknown[]) => unknown;

85

```

86

87

**Usage Examples:**

88

89

```typescript

90

import { isType } from "is-what";

91

92

// Built-in constructors

93

isType("hello", String); // true

94

isType(new String("hello"), String); // true

95

isType(42, Number); // true

96

isType(NaN, Number); // true (unlike isNumber())

97

isType([], Array); // true

98

isType(new Date(), Date); // true

99

100

// Custom classes

101

class MyClass {

102

constructor(public name: string) {}

103

}

104

105

class OtherClass {}

106

107

const instance = new MyClass("test");

108

isType(instance, MyClass); // true

109

isType(instance, OtherClass); // false

110

111

if (isType(value, Date)) {

112

// TypeScript knows value is Date

113

console.log(value.getFullYear());

114

}

115

116

// Practical usage

117

function validateType<T extends AnyClass>(

118

value: unknown,

119

expectedType: T,

120

fieldName: string

121

): T {

122

if (isType(value, expectedType)) {

123

return value;

124

}

125

126

throw new Error(

127

`${fieldName} must be of type ${expectedType.name}, got ${getType(value)}`

128

);

129

}

130

131

// Generic type checker factory

132

function createTypeChecker<T extends AnyClass>(type: T) {

133

return (value: unknown): value is T => {

134

try {

135

return isType(value, type);

136

} catch {

137

return false;

138

}

139

};

140

}

141

142

const isDateInstance = createTypeChecker(Date);

143

const isArrayInstance = createTypeChecker(Array);

144

145

// Error handling - function throws TypeError for invalid types

146

try {

147

isType("test", "NotAConstructor" as any); // Throws TypeError

148

} catch (error) {

149

console.log("Invalid type provided");

150

}

151

```

152

153

### Instance Detection

154

155

Checks if a value is an instance of a class or matches a class name. Useful when you want to check for types that may not be defined in the current scope.

156

157

```typescript { .api }

158

/**

159

* Checks if a value is an instance of a class or a class name.

160

* Useful when you want to check if a value is an instance of a class

161

* that may not be defined in the current scope.

162

* @param value - The value to recursively check

163

* @param classOrClassName - A class constructor or string class name

164

* @returns Type guard indicating if value is instance of the specified class

165

*/

166

function isInstanceOf<T extends AnyClass>(value: unknown, class_: T): value is T;

167

function isInstanceOf<K extends GlobalClassName>(

168

value: unknown,

169

className: K

170

): value is (typeof globalThis)[K];

171

function isInstanceOf(value: unknown, className: string): value is object;

172

function isInstanceOf(value: unknown, classOrClassName: AnyClass | string): boolean;

173

```

174

175

**Usage Examples:**

176

177

```typescript

178

import { isInstanceOf } from "is-what";

179

180

// Class constructor checking

181

class MyClass {

182

constructor(public name: string) {}

183

}

184

185

class ChildClass extends MyClass {

186

constructor(name: string, public age: number) {

187

super(name);

188

}

189

}

190

191

const parent = new MyClass("parent");

192

const child = new ChildClass("child", 25);

193

194

isInstanceOf(parent, MyClass); // true

195

isInstanceOf(child, MyClass); // true (inheritance)

196

isInstanceOf(child, ChildClass); // true

197

isInstanceOf(parent, ChildClass); // false

198

199

// String-based class name checking (useful for cross-context checks)

200

isInstanceOf(new Date(), "Date"); // true

201

isInstanceOf([], "Array"); // true

202

isInstanceOf({}, "Object"); // true

203

isInstanceOf(new Error(), "Error"); // true

204

205

// Browser-specific types (when available)

206

if (typeof OffscreenCanvas !== 'undefined') {

207

const canvas = new OffscreenCanvas(100, 100);

208

isInstanceOf(canvas, "OffscreenCanvas"); // true

209

}

210

211

// Practical usage - checking for types that might not exist

212

function handleCanvasLikeObject(obj: unknown) {

213

if (isInstanceOf(obj, "HTMLCanvasElement")) {

214

// Handle HTML canvas

215

return obj.getContext("2d");

216

}

217

218

if (isInstanceOf(obj, "OffscreenCanvas")) {

219

// Handle OffscreenCanvas (if available)

220

return obj.getContext("2d");

221

}

222

223

throw new Error("Expected canvas-like object");

224

}

225

226

// Inheritance-aware validation

227

function validateUserModel(obj: unknown) {

228

if (isInstanceOf(obj, MyClass)) {

229

// Works for MyClass and any subclass

230

return {

231

name: obj.name,

232

type: obj.constructor.name

233

};

234

}

235

236

throw new Error("Object must be instance of MyClass or its subclasses");

237

}

238

239

// Cross-frame/context checking (using string names)

240

function isArrayLike(value: unknown) {

241

return isInstanceOf(value, "Array") ||

242

(typeof value === "object" &&

243

value !== null &&

244

"length" in value);

245

}

246

```

247

248

### Factory Function for Union Types

249

250

A factory function that creates a function to check if the payload is one of the given types. Supports 2-5 type guards with proper TypeScript union type inference.

251

252

```typescript { .api }

253

/**

254

* A factory function that creates a function to check if the payload is one of the given types.

255

*/

256

function isOneOf<A, B extends A, C extends A>(

257

a: TypeGuard<A, B>,

258

b: TypeGuard<A, C>

259

): TypeGuard<A, B | C>;

260

261

function isOneOf<A, B extends A, C extends A, D extends A>(

262

a: TypeGuard<A, B>,

263

b: TypeGuard<A, C>,

264

c: TypeGuard<A, D>

265

): TypeGuard<A, B | C | D>;

266

267

function isOneOf<A, B extends A, C extends A, D extends A, E extends A>(

268

a: TypeGuard<A, B>,

269

b: TypeGuard<A, C>,

270

c: TypeGuard<A, D>,

271

d: TypeGuard<A, E>

272

): TypeGuard<A, B | C | D | E>;

273

274

function isOneOf<A, B extends A, C extends A, D extends A, E extends A, F extends A>(

275

a: TypeGuard<A, B>,

276

b: TypeGuard<A, C>,

277

c: TypeGuard<A, D>,

278

d: TypeGuard<A, E>,

279

e: TypeGuard<A, F>

280

): TypeGuard<A, B | C | D | E | F>;

281

282

type TypeGuard<A, B extends A> = (payload: A) => payload is B;

283

```

284

285

**Usage Examples:**

286

287

```typescript

288

import { isOneOf, isNull, isUndefined, isString, isNumber } from "is-what";

289

290

// Create composite type checkers

291

const isNullOrUndefined = isOneOf(isNull, isUndefined);

292

const isStringOrNumber = isOneOf(isString, isNumber);

293

294

// Usage

295

isNullOrUndefined(null); // true

296

isNullOrUndefined(undefined); // true

297

isNullOrUndefined("hello"); // false

298

299

isStringOrNumber("hello"); // true

300

isStringOrNumber(42); // true

301

isStringOrNumber(true); // false

302

303

// TypeScript type narrowing works correctly

304

function processValue(value: unknown) {

305

if (isNullOrUndefined(value)) {

306

// TypeScript knows value is null | undefined

307

console.log("No value provided");

308

return null;

309

}

310

311

if (isStringOrNumber(value)) {

312

// TypeScript knows value is string | number

313

return value.toString(); // Both types have toString()

314

}

315

316

return "Other type";

317

}

318

319

// Complex combinations

320

const isPrimitiveOrNull = isOneOf(

321

isString,

322

isNumber,

323

isNull

324

);

325

326

// Custom type guards with isOneOf

327

function isEven(value: unknown): value is number {

328

return isNumber(value) && value % 2 === 0;

329

}

330

331

function isOdd(value: unknown): value is number {

332

return isNumber(value) && value % 2 === 1;

333

}

334

335

const isEvenOrOdd = isOneOf(isEven, isOdd);

336

337

// Practical usage - form validation

338

const isValidId = isOneOf(isString, isNumber);

339

340

function validateUserId(id: unknown) {

341

if (isValidId(id)) {

342

// TypeScript knows id is string | number

343

return { valid: true, id: id.toString() };

344

}

345

346

return { valid: false, error: "ID must be string or number" };

347

}

348

349

// API response validation

350

import { isArray, isObject } from "is-what";

351

352

const isArrayOrObject = isOneOf(isArray, isPlainObject);

353

354

function processApiResponse(response: unknown) {

355

if (isArrayOrObject(response)) {

356

// TypeScript knows response is unknown[] | PlainObject

357

return JSON.stringify(response, null, 2);

358

}

359

360

throw new Error("API response must be array or object");

361

}

362

363

// Error handling combinations

364

import { isError } from "is-what";

365

366

const isErrorOrString = isOneOf(isError, isString);

367

368

function handleResult(result: unknown) {

369

if (isErrorOrString(result)) {

370

// TypeScript knows result is Error | string

371

const message = isError(result) ? result.message : result;

372

console.log("Error:", message);

373

return null;

374

}

375

376

return result; // Success case

377

}

378

```

379

380

## Combined Generic Utility Patterns

381

382

```typescript

383

import {

384

getType,

385

isType,

386

isInstanceOf,

387

isOneOf,

388

isString,

389

isNumber,

390

isFunction

391

} from "is-what";

392

393

// Advanced type analysis

394

function analyzeTypeComprehensively(value: unknown) {

395

const basicType = getType(value);

396

const analysis = { basicType, details: {} as any };

397

398

// Check against common constructors

399

const constructors = [String, Number, Boolean, Array, Object, Date, RegExp];

400

for (const ctor of constructors) {

401

try {

402

if (isType(value, ctor)) {

403

analysis.details[ctor.name] = true;

404

}

405

} catch {

406

// Skip invalid constructors

407

}

408

}

409

410

// Check inheritance patterns

411

if (value && typeof value === "object") {

412

analysis.details.constructor = value.constructor?.name || "Unknown";

413

analysis.details.hasPrototype = Object.getPrototypeOf(value) !== null;

414

}

415

416

return analysis;

417

}

418

419

// Generic validation system

420

class TypeValidator {

421

private validators = new Map<string, (value: unknown) => boolean>();

422

423

register(name: string, validator: (value: unknown) => boolean) {

424

this.validators.set(name, validator);

425

}

426

427

validate(value: unknown, typeName: string) {

428

const validator = this.validators.get(typeName);

429

if (!validator) {

430

throw new Error(`Unknown type validator: ${typeName}`);

431

}

432

433

return validator(value);

434

}

435

436

createCompositeValidator(...typeNames: string[]) {

437

const validators = typeNames.map(name => this.validators.get(name))

438

.filter(Boolean);

439

440

return (value: unknown) => validators.some(validator => validator!(value));

441

}

442

}

443

444

// Usage

445

const validator = new TypeValidator();

446

validator.register("string", isString);

447

validator.register("number", isNumber);

448

validator.register("function", isFunction);

449

450

const isStringOrNumber = validator.createCompositeValidator("string", "number");

451

452

// Type-safe object creation

453

function createTypedObject<T extends AnyClass>(

454

type: T,

455

...args: ConstructorParameters<T>

456

): InstanceType<T> {

457

const instance = new type(...args);

458

459

if (isInstanceOf(instance, type)) {

460

return instance as InstanceType<T>;

461

}

462

463

throw new Error(`Failed to create instance of ${type.name}`);

464

}

465

466

// Example usage

467

const analysis = analyzeTypeComprehensively(new Date());

468

// Returns: {

469

// basicType: "Date",

470

// details: {

471

// Date: true,

472

// Object: true,

473

// constructor: "Date",

474

// hasPrototype: true

475

// }

476

// }

477

478

class User {

479

constructor(public name: string, public age: number) {}

480

}

481

482

const user = createTypedObject(User, "Alice", 30);

483

// TypeScript knows user is User instance

484

console.log(user.name); // "Alice"

485

```

486

487

## Types

488

489

```typescript { .api }

490

type AnyClass = new (...args: unknown[]) => unknown;

491

type TypeGuard<A, B extends A> = (payload: A) => payload is B;

492

493

type GlobalClassName = {

494

[K in keyof typeof globalThis]: (typeof globalThis)[K] extends AnyClass ? K : never;

495

}[keyof typeof globalThis];

496

```