or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aliases-guards.mdflow-utilities.mdindex.mdmapped-types.md

aliases-guards.mddocs/

0

# Type Aliases and Guards

1

2

Type aliases and guards provide common type definitions with corresponding runtime type guard functions for type checking at runtime. These utilities bridge compile-time type safety with runtime type validation.

3

4

## Import

5

6

```typescript

7

import {

8

// Type aliases

9

Primitive, Falsy, Falsey, Nullish,

10

11

// Type guard functions

12

isPrimitive, isFalsy, isNullish

13

} from 'utility-types';

14

```

15

16

For CommonJS:

17

18

```javascript

19

const {

20

// Type aliases

21

Primitive, Falsy, Falsey, Nullish,

22

23

// Type guard functions

24

isPrimitive, isFalsy, isNullish

25

} = require('utility-types');

26

```

27

28

## Type Aliases

29

30

### Primitive

31

32

Represents JavaScript primitive types: string, number, bigint, boolean, symbol, null, and undefined.

33

34

```typescript { .api }

35

type Primitive = string | number | bigint | boolean | symbol | null | undefined;

36

```

37

38

**Usage:**

39

40

```typescript

41

// Type checking

42

function isSimpleValue(value: unknown): value is Primitive {

43

return value !== Object(value);

44

}

45

46

// Excluding complex types

47

type SimpleData<T> = T extends Primitive ? T : never;

48

49

type Example1 = SimpleData<string>; // Result: string

50

type Example2 = SimpleData<object>; // Result: never

51

52

// Filtering object properties

53

interface MixedData {

54

id: number;

55

name: string;

56

settings: object;

57

callback: () => void;

58

isActive: boolean;

59

metadata: Record<string, any>;

60

}

61

62

type PrimitiveFields = {

63

[K in keyof MixedData]: MixedData[K] extends Primitive ? K : never;

64

}[keyof MixedData];

65

// Result: 'id' | 'name' | 'isActive'

66

67

type PrimitiveData = Pick<MixedData, PrimitiveFields>;

68

// Result: { id: number; name: string; isActive: boolean; }

69

70

// Practical usage in serialization

71

function serializePrimitives<T extends Record<string, any>>(obj: T): Pick<T, {

72

[K in keyof T]: T[K] extends Primitive ? K : never;

73

}[keyof T]> {

74

const result = {} as any;

75

for (const [key, value] of Object.entries(obj)) {

76

if (value !== Object(value)) {

77

result[key] = value;

78

}

79

}

80

return result;

81

}

82

```

83

84

### Falsy

85

86

Represents JavaScript falsy values: false, empty string, 0, null, and undefined.

87

88

```typescript { .api }

89

type Falsy = false | '' | 0 | null | undefined;

90

```

91

92

**Usage:**

93

94

```typescript

95

// Remove falsy values from union types

96

type TruthyString = Exclude<string, Falsy>;

97

// Result: string (but excludes empty string)

98

99

type TruthyNumber = Exclude<number, Falsy>;

100

// Result: number (but excludes 0)

101

102

// Filter arrays to remove falsy values

103

function filterTruthy<T>(array: T[]): Array<Exclude<T, Falsy>> {

104

return array.filter(Boolean) as Array<Exclude<T, Falsy>>;

105

}

106

107

const mixed = [1, 0, 'hello', '', true, false, null, undefined];

108

const truthy = filterTruthy(mixed);

109

// Type: Array<1 | 'hello' | true>

110

// Value: [1, 'hello', true]

111

112

// Conditional type based on falsy check

113

type IsTruthy<T> = T extends Falsy ? false : true;

114

115

type Test1 = IsTruthy<0>; // Result: false

116

type Test2 = IsTruthy<42>; // Result: true

117

type Test3 = IsTruthy<''>; // Result: false

118

type Test4 = IsTruthy<'hello'>; // Result: true

119

120

// Default value patterns

121

function withDefault<T>(value: T | Falsy, defaultValue: T): T {

122

return value || defaultValue;

123

}

124

125

const result1 = withDefault('', 'default'); // Result: 'default'

126

const result2 = withDefault('value', 'default'); // Result: 'value'

127

```

128

129

### Falsey (Deprecated)

130

131

Deprecated alias for `Falsy`. Provided for backward compatibility until v4.

132

133

```typescript { .api }

134

type Falsey = Falsy;

135

```

136

137

**Usage:**

138

139

```typescript

140

// Deprecated - use Falsy instead

141

type OldFalseyType = Falsey;

142

143

// Preferred

144

type NewFalsyType = Falsy;

145

146

// Migration guide

147

function migrationExample(value: unknown): value is Falsy {

148

// Old: value is Falsey

149

// New: value is Falsy

150

return !value;

151

}

152

```

153

154

### Nullish

155

156

Represents nullish values in TypeScript: null and undefined.

157

158

```typescript { .api }

159

type Nullish = null | undefined;

160

```

161

162

**Usage:**

163

164

```typescript

165

// Nullish coalescing patterns

166

function withNullishDefault<T>(value: T | Nullish, defaultValue: T): T {

167

return value ?? defaultValue;

168

}

169

170

const result1 = withNullishDefault(null, 'default'); // Result: 'default'

171

const result2 = withNullishDefault(undefined, 'default'); // Result: 'default'

172

const result3 = withNullishDefault('', 'default'); // Result: '' (empty string is not nullish)

173

const result4 = withNullishDefault(0, 42); // Result: 0 (zero is not nullish)

174

175

// Remove nullish values from union types

176

type NonNullishString = Exclude<string | null | undefined, Nullish>;

177

// Result: string

178

179

// Optional property handling

180

interface Config {

181

host?: string;

182

port?: number;

183

timeout?: number;

184

}

185

186

type RequiredConfig = {

187

[K in keyof Config]-?: Exclude<Config[K], Nullish>;

188

};

189

// Result: { host: string; port: number; timeout: number; }

190

191

// Array filtering

192

function filterNullish<T>(array: Array<T | Nullish>): T[] {

193

return array.filter((item): item is T => item != null);

194

}

195

196

const withNulls = [1, null, 2, undefined, 3];

197

const withoutNulls = filterNullish(withNulls);

198

// Type: number[]

199

// Value: [1, 2, 3]

200

201

// Conditional types

202

type IsNullish<T> = T extends Nullish ? true : false;

203

204

type Test1 = IsNullish<null>; // Result: true

205

type Test2 = IsNullish<undefined>; // Result: true

206

type Test3 = IsNullish<0>; // Result: false

207

type Test4 = IsNullish<''>; // Result: false

208

```

209

210

## Type Guard Functions

211

212

### isPrimitive

213

214

Runtime type guard to check if a value is a primitive type.

215

216

```typescript { .api }

217

function isPrimitive(val: unknown): val is Primitive;

218

```

219

220

**Usage:**

221

222

```typescript

223

// Basic usage

224

const value1: unknown = 'hello';

225

const value2: unknown = { name: 'John' };

226

const value3: unknown = [1, 2, 3];

227

228

if (isPrimitive(value1)) {

229

// value1 is now typed as Primitive

230

console.log(typeof value1); // Safe to use

231

}

232

233

if (isPrimitive(value2)) {

234

// This block won't execute - objects are not primitive

235

} else {

236

// value2 is unknown but we know it's not primitive

237

console.log('Complex type');

238

}

239

240

// Filtering arrays

241

const mixedArray: unknown[] = [1, 'hello', {}, [], true, null, undefined, Symbol('test')];

242

243

const primitives = mixedArray.filter(isPrimitive);

244

// Type: Primitive[]

245

// Contains: [1, 'hello', true, null, undefined, Symbol('test')]

246

247

const nonPrimitives = mixedArray.filter(item => !isPrimitive(item));

248

// Type: unknown[] (but we know they're not primitive)

249

// Contains: [{}, []]

250

251

// Type-safe serialization

252

function safeSerialization(data: Record<string, unknown>): Record<string, Primitive> {

253

const result: Record<string, Primitive> = {};

254

255

for (const [key, value] of Object.entries(data)) {

256

if (isPrimitive(value)) {

257

result[key] = value; // Type-safe assignment

258

}

259

}

260

261

return result;

262

}

263

264

// Form data processing

265

function processFormData(formData: Record<string, unknown>) {

266

const primitiveData: Record<string, Primitive> = {};

267

const complexData: Record<string, unknown> = {};

268

269

for (const [key, value] of Object.entries(formData)) {

270

if (isPrimitive(value)) {

271

primitiveData[key] = value;

272

} else {

273

complexData[key] = value;

274

}

275

}

276

277

return { primitiveData, complexData };

278

}

279

```

280

281

### isFalsy

282

283

Runtime type guard to check if a value is falsy.

284

285

```typescript { .api }

286

function isFalsy(val: unknown): val is Falsy;

287

```

288

289

**Usage:**

290

291

```typescript

292

// Basic usage

293

const values = [0, '', false, null, undefined, 'hello', 1, true, {}];

294

295

const falsyValues = values.filter(isFalsy);

296

// Type: Falsy[]

297

// Contains: [0, '', false, null, undefined]

298

299

const truthyValues = values.filter(val => !isFalsy(val));

300

// Type: unknown[] (but we know they're truthy)

301

// Contains: ['hello', 1, true, {}]

302

303

// Form validation

304

function validateFormField(value: unknown): string | null {

305

if (isFalsy(value)) {

306

return 'Field is required';

307

}

308

309

// value is now typed as Exclude<unknown, Falsy>

310

// We know it's not falsy

311

return null;

312

}

313

314

// Array compaction

315

function compact<T>(array: T[]): Array<Exclude<T, Falsy>> {

316

return array.filter((item): item is Exclude<T, Falsy> => !isFalsy(item));

317

}

318

319

const messyArray = [1, 0, 'test', '', true, false, null, undefined, 'hello'];

320

const cleanArray = compact(messyArray);

321

// Type: Array<1 | 'test' | true | 'hello'>

322

// Value: [1, 'test', true, 'hello']

323

324

// Configuration with defaults

325

interface PartialConfig {

326

host?: string | null;

327

port?: number | null;

328

secure?: boolean | null;

329

}

330

331

function applyConfigDefaults(config: PartialConfig): Required<PartialConfig> {

332

return {

333

host: isFalsy(config.host) ? 'localhost' : config.host,

334

port: isFalsy(config.port) ? 8080 : config.port,

335

secure: isFalsy(config.secure) ? false : config.secure

336

};

337

}

338

339

// Conditional rendering helper

340

function renderIfTruthy<T>(value: T, render: (val: Exclude<T, Falsy>) => JSX.Element): JSX.Element | null {

341

if (isFalsy(value)) {

342

return null;

343

}

344

return render(value as Exclude<T, Falsy>);

345

}

346

```

347

348

### isNullish

349

350

Runtime type guard to check if a value is nullish (null or undefined).

351

352

```typescript { .api }

353

function isNullish(val: unknown): val is Nullish;

354

```

355

356

**Usage:**

357

358

```typescript

359

// Basic usage

360

const values = [null, undefined, 0, '', false, 'hello', 1, {}];

361

362

const nullishValues = values.filter(isNullish);

363

// Type: Nullish[]

364

// Contains: [null, undefined]

365

366

const nonNullishValues = values.filter(val => !isNullish(val));

367

// Type: unknown[] (but we know they're not nullish)

368

// Contains: [0, '', false, 'hello', 1, {}]

369

370

// Nullish coalescing with type safety

371

function safeAccess<T>(value: T | Nullish, defaultValue: T): T {

372

if (isNullish(value)) {

373

return defaultValue;

374

}

375

return value; // TypeScript knows value is T here

376

}

377

378

const result1 = safeAccess(null, 'default'); // Result: 'default'

379

const result2 = safeAccess(undefined, 'default'); // Result: 'default'

380

const result3 = safeAccess('value', 'default'); // Result: 'value'

381

const result4 = safeAccess(0, 42); // Result: 0 (zero is not nullish)

382

383

// Optional property processing

384

interface User {

385

id: number;

386

name?: string;

387

email?: string;

388

avatar?: string;

389

}

390

391

function processUser(user: User): Required<User> {

392

return {

393

id: user.id,

394

name: isNullish(user.name) ? 'Anonymous' : user.name,

395

email: isNullish(user.email) ? 'no-email@example.com' : user.email,

396

avatar: isNullish(user.avatar) ? '/default-avatar.png' : user.avatar

397

};

398

}

399

400

// Database result processing

401

type DatabaseResult<T> = T | null | undefined;

402

403

function processResults<T>(results: DatabaseResult<T>[]): T[] {

404

return results.filter((result): result is T => !isNullish(result));

405

}

406

407

const dbResults: DatabaseResult<string>[] = ['user1', null, 'user2', undefined, 'user3'];

408

const validResults = processResults(dbResults);

409

// Type: string[]

410

// Value: ['user1', 'user2', 'user3']

411

412

// API response handling

413

interface ApiResponse<T> {

414

data?: T;

415

error?: string;

416

status: number;

417

}

418

419

function extractData<T>(response: ApiResponse<T>): T | null {

420

if (response.status !== 200) {

421

return null;

422

}

423

424

if (isNullish(response.data)) {

425

return null;

426

}

427

428

return response.data; // TypeScript knows data is T here

429

}

430

431

// Form data validation

432

function validateNonNullishFields<T extends Record<string, any>>(

433

data: T

434

): Record<keyof T, Exclude<T[keyof T], Nullish>> | string[] {

435

const errors: string[] = [];

436

const validated = {} as any;

437

438

for (const [key, value] of Object.entries(data)) {

439

if (isNullish(value)) {

440

errors.push(`${key} is required`);

441

} else {

442

validated[key] = value;

443

}

444

}

445

446

return errors.length > 0 ? errors : validated;

447

}

448

```

449

450

## Combined Usage Examples

451

452

### Type-Safe Data Processing Pipeline

453

454

```typescript

455

// Comprehensive data processing using all utilities

456

interface RawData {

457

id?: number | null;

458

name?: string | null;

459

email?: string | null;

460

score?: number | null;

461

metadata?: Record<string, unknown> | null;

462

}

463

464

function processRawData(items: RawData[]): ProcessedData[] {

465

return items

466

.filter(item => !isNullish(item))

467

.map(item => {

468

// Extract primitive fields

469

const primitiveFields: Record<string, Primitive> = {};

470

const complexFields: Record<string, unknown> = {};

471

472

for (const [key, value] of Object.entries(item)) {

473

if (!isNullish(value)) {

474

if (isPrimitive(value)) {

475

primitiveFields[key] = value;

476

} else {

477

complexFields[key] = value;

478

}

479

}

480

}

481

482

return {

483

id: primitiveFields.id ?? 0,

484

name: isFalsy(primitiveFields.name) ? 'Unknown' : primitiveFields.name as string,

485

email: isFalsy(primitiveFields.email) ? null : primitiveFields.email as string,

486

score: primitiveFields.score ?? 0,

487

hasMetadata: !isNullish(complexFields.metadata)

488

};

489

});

490

}

491

492

interface ProcessedData {

493

id: number;

494

name: string;

495

email: string | null;

496

score: number;

497

hasMetadata: boolean;

498

}

499

```

500

501

### Type Guard Composition

502

503

```typescript

504

// Combining type guards for complex validation

505

function isValidPrimitive(value: unknown): value is Exclude<Primitive, Nullish | Falsy> {

506

return isPrimitive(value) && !isNullish(value) && !isFalsy(value);

507

}

508

509

function isValidString(value: unknown): value is string {

510

return typeof value === 'string' && !isFalsy(value);

511

}

512

513

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

514

return typeof value === 'number' && !isFalsy(value) && !isNaN(value);

515

}

516

517

// Usage in validation schemas

518

interface ValidationSchema {

519

[key: string]: (value: unknown) => boolean;

520

}

521

522

const userValidation: ValidationSchema = {

523

id: isValidNumber,

524

name: isValidString,

525

email: (value): value is string =>

526

isValidString(value) && /\S+@\S+\.\S+/.test(value),

527

age: (value): value is number =>

528

isValidNumber(value) && value >= 0 && value <= 150

529

};

530

531

function validateUser(userData: Record<string, unknown>): boolean {

532

return Object.entries(userValidation).every(([key, validator]) =>

533

validator(userData[key])

534

);

535

}

536

```

537

538

## Deprecated Functions

539

540

### getReturnOfExpression (Deprecated)

541

542

**Deprecated** function for inferring return types from expressions. Use TypeScript's built-in `ReturnType<T>` or `$Call` API instead.

543

544

```typescript { .api }

545

function getReturnOfExpression<RT>(expression: (...params: any[]) => RT): RT;

546

```

547

548

**Usage:**

549

550

```typescript

551

// DEPRECATED - Do not use in new code

552

import { getReturnOfExpression } from 'utility-types';

553

554

const increment = () => ({ type: 'INCREMENT' as 'INCREMENT' });

555

type IncrementType = typeof getReturnOfExpression<typeof increment>;

556

// Result: { type: "INCREMENT"; }

557

558

// PREFERRED - Use these instead:

559

type IncrementTypeModern1 = ReturnType<typeof increment>;

560

type IncrementTypeModern2 = $Call<typeof increment>;

561

```

562

563

**Migration Guide:**

564

565

```typescript

566

// Old way (deprecated):

567

const myFunction = (x: number) => ({ result: x * 2 });

568

type OldReturnType = typeof getReturnOfExpression<typeof myFunction>;

569

570

// New way (preferred):

571

type NewReturnType = ReturnType<typeof myFunction>;

572

// or

573

type AlternativeReturnType = $Call<typeof myFunction>;

574

```

575

576

**Note**: This function was deprecated in TypeScript v2.8 when `ReturnType<T>` was introduced. It returns `undefined` at runtime but provides correct type information at compile time.

577

```