or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdbenchmarking.mdbrowser-testing.mdconfiguration.mdindex.mdmocking.mdnode-apis.mdreporters.mdtest-definition.mdtimers.mdtype-testing.md

type-testing.mddocs/

0

# Type Testing

1

2

Vitest provides type-level testing capabilities for ensuring TypeScript types are correct without runtime execution.

3

4

## Capabilities

5

6

### ExpectTypeOf

7

8

Type-level assertions using the `expectTypeOf` function from the `expect-type` library.

9

10

```typescript { .api }

11

/**

12

* Create type-level expectation

13

* @param value - Value to check types for

14

* @returns Type-level assertion object

15

*/

16

function expectTypeOf<T>(value: T): ExpectTypeOf<T>;

17

function expectTypeOf<T>(): ExpectTypeOf<T>;

18

19

interface ExpectTypeOf<T> {

20

/** Assert type is exactly equal to Expected */

21

toEqualTypeOf<Expected>(): void;

22

23

/** Assert type matches Expected structure */

24

toMatchTypeOf<Expected>(): void;

25

26

/** Assert type is any */

27

toBeAny(): void;

28

29

/** Assert type is unknown */

30

toBeUnknown(): void;

31

32

/** Assert type is never */

33

toBeNever(): void;

34

35

/** Assert type is a function */

36

toBeFunction(): void;

37

38

/** Assert type is an object */

39

toBeObject(): void;

40

41

/** Assert type is an array */

42

toBeArray(): void;

43

44

/** Assert type is a string */

45

toBeString(): void;

46

47

/** Assert type is a number */

48

toBeNumber(): void;

49

50

/** Assert type is a boolean */

51

toBeBoolean(): void;

52

53

/** Assert type is void */

54

toBeVoid(): void;

55

56

/** Assert type is null */

57

toBeNull(): void;

58

59

/** Assert type is undefined */

60

toBeUndefined(): void;

61

62

/** Assert type is nullable (null or undefined) */

63

toBeNullable(): void;

64

65

/** Assert type has callable signature */

66

toBeCallableWith(...args: any[]): void;

67

68

/** Assert type can be constructed */

69

toBeConstructibleWith(...args: any[]): void;

70

71

/** Assert type has property */

72

toHaveProperty<K extends keyof T>(key: K): ExpectTypeOf<T[K]>;

73

74

/** Negate assertion */

75

not: ExpectTypeOf<T>;

76

77

/** Extract type from Promise */

78

resolves: T extends Promise<infer U> ? ExpectTypeOf<U> : never;

79

80

/** Extract parameters from function */

81

parameters: T extends (...args: infer P) => any ? ExpectTypeOf<P> : never;

82

83

/** Extract return type from function */

84

returns: T extends (...args: any[]) => infer R ? ExpectTypeOf<R> : never;

85

86

/** Extract type from array */

87

items: T extends (infer Item)[] ? ExpectTypeOf<Item> : never;

88

89

/** Extract branded type */

90

branded: ExpectTypeOf<T>;

91

}

92

```

93

94

**Usage:**

95

96

```typescript

97

import { test, expectTypeOf } from 'vitest';

98

99

test('type assertions', () => {

100

// Exact type equality

101

expectTypeOf<string>().toEqualTypeOf<string>();

102

expectTypeOf('hello').toEqualTypeOf<string>();

103

104

// Structural matching

105

expectTypeOf<{ a: number }>().toMatchTypeOf<{ a: number }>();

106

107

// Primitive types

108

expectTypeOf('').toBeString();

109

expectTypeOf(123).toBeNumber();

110

expectTypeOf(true).toBeBoolean();

111

expectTypeOf(null).toBeNull();

112

expectTypeOf(undefined).toBeUndefined();

113

expectTypeOf({}).toBeObject();

114

expectTypeOf([]).toBeArray();

115

expectTypeOf(() => {}).toBeFunction();

116

117

// Never and any

118

expectTypeOf<never>().toBeNever();

119

expectTypeOf<any>().toBeAny();

120

expectTypeOf<unknown>().toBeUnknown();

121

122

// Nullable

123

expectTypeOf<string | null>().toBeNullable();

124

expectTypeOf<string | undefined>().toBeNullable();

125

126

// Negation

127

expectTypeOf<number>().not.toBeString();

128

expectTypeOf<string>().not.toBeNumber();

129

});

130

```

131

132

### Function Type Testing

133

134

Test function signatures, parameters, and return types.

135

136

```typescript

137

import { test, expectTypeOf } from 'vitest';

138

139

test('function types', () => {

140

const add = (a: number, b: number): number => a + b;

141

142

// Check if callable

143

expectTypeOf(add).toBeCallableWith(1, 2);

144

145

// Check parameters

146

expectTypeOf(add).parameters.toEqualTypeOf<[number, number]>();

147

148

// Check return type

149

expectTypeOf(add).returns.toEqualTypeOf<number>();

150

});

151

152

test('constructor types', () => {

153

class User {

154

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

155

}

156

157

expectTypeOf(User).toBeConstructibleWith('John', 30);

158

expectTypeOf(User).instance.toHaveProperty('name');

159

expectTypeOf(User).instance.toHaveProperty('age');

160

});

161

```

162

163

### Object Type Testing

164

165

Test object structure and properties.

166

167

```typescript

168

import { test, expectTypeOf } from 'vitest';

169

170

test('object types', () => {

171

type User = {

172

id: number;

173

name: string;

174

email?: string;

175

};

176

177

// Exact type match

178

expectTypeOf<User>().toEqualTypeOf<{

179

id: number;

180

name: string;

181

email?: string;

182

}>();

183

184

// Structural match (allows extra properties)

185

expectTypeOf<User>().toMatchTypeOf<{

186

id: number;

187

name: string;

188

}>();

189

190

// Property types

191

expectTypeOf<User>().toHaveProperty('id').toBeNumber();

192

expectTypeOf<User>().toHaveProperty('name').toBeString();

193

expectTypeOf<User>().toHaveProperty('email').toEqualTypeOf<string | undefined>();

194

});

195

```

196

197

### Generic Type Testing

198

199

Test generic types and type parameters.

200

201

```typescript

202

import { test, expectTypeOf } from 'vitest';

203

204

test('generic types', () => {

205

// Array item types

206

expectTypeOf<string[]>().items.toBeString();

207

expectTypeOf<number[]>().items.toBeNumber();

208

209

// Promise resolution types

210

expectTypeOf<Promise<string>>().resolves.toBeString();

211

expectTypeOf<Promise<number>>().resolves.toBeNumber();

212

213

// Generic function return types

214

function identity<T>(value: T): T {

215

return value;

216

}

217

218

expectTypeOf(identity<string>).returns.toBeString();

219

expectTypeOf(identity<number>).returns.toBeNumber();

220

});

221

```

222

223

### Union and Intersection Types

224

225

```typescript

226

import { test, expectTypeOf } from 'vitest';

227

228

test('union types', () => {

229

type StringOrNumber = string | number;

230

231

expectTypeOf<StringOrNumber>().toMatchTypeOf<string>();

232

expectTypeOf<StringOrNumber>().toMatchTypeOf<number>();

233

expectTypeOf<string>().toMatchTypeOf<StringOrNumber>();

234

});

235

236

test('intersection types', () => {

237

type Named = { name: string };

238

type Aged = { age: number };

239

type Person = Named & Aged;

240

241

expectTypeOf<Person>().toHaveProperty('name').toBeString();

242

expectTypeOf<Person>().toHaveProperty('age').toBeNumber();

243

expectTypeOf<Person>().toMatchTypeOf<Named>();

244

expectTypeOf<Person>().toMatchTypeOf<Aged>();

245

});

246

```

247

248

### AssertType

249

250

Runtime-free type assertions for checking type compatibility.

251

252

```typescript { .api }

253

/**

254

* Assert that value matches type T

255

* Causes TypeScript error if types don't match

256

* @param value - Value to type check

257

*/

258

function assertType<T>(value: T): void;

259

```

260

261

**Usage:**

262

263

```typescript

264

import { test, assertType } from 'vitest';

265

266

test('assert types', () => {

267

const value: string = 'hello';

268

269

assertType<string>(value); // OK

270

// assertType<number>(value); // TypeScript error

271

272

const obj = { id: 1, name: 'John' };

273

274

assertType<{ id: number; name: string }>(obj); // OK

275

276

const promise = Promise.resolve(42);

277

278

assertType<Promise<number>>(promise); // OK

279

});

280

```

281

282

### Complex Type Scenarios

283

284

```typescript

285

import { test, expectTypeOf } from 'vitest';

286

287

test('conditional types', () => {

288

type IsString<T> = T extends string ? true : false;

289

290

expectTypeOf<IsString<string>>().toEqualTypeOf<true>();

291

expectTypeOf<IsString<number>>().toEqualTypeOf<false>();

292

});

293

294

test('mapped types', () => {

295

type Readonly<T> = {

296

readonly [K in keyof T]: T[K];

297

};

298

299

type User = { name: string; age: number };

300

type ReadonlyUser = Readonly<User>;

301

302

expectTypeOf<ReadonlyUser>().toEqualTypeOf<{

303

readonly name: string;

304

readonly age: number;

305

}>();

306

});

307

308

test('utility types', () => {

309

type User = { id: number; name: string; email: string };

310

311

expectTypeOf<Partial<User>>().toEqualTypeOf<{

312

id?: number;

313

name?: string;

314

email?: string;

315

}>();

316

317

expectTypeOf<Required<User>>().toEqualTypeOf<{

318

id: number;

319

name: string;

320

email: string;

321

}>();

322

323

expectTypeOf<Pick<User, 'id' | 'name'>>().toEqualTypeOf<{

324

id: number;

325

name: string;

326

}>();

327

328

expectTypeOf<Omit<User, 'email'>>().toEqualTypeOf<{

329

id: number;

330

name: string;

331

}>();

332

});

333

```

334

335

## Typecheck Configuration

336

337

Configure type checking in vitest.config.ts:

338

339

```typescript

340

import { defineConfig } from 'vitest/config';

341

342

export default defineConfig({

343

test: {

344

typecheck: {

345

enabled: true,

346

checker: 'tsc', // or 'vue-tsc'

347

include: ['**/*.{test,spec}-d.ts'],

348

exclude: ['node_modules'],

349

tsconfig: './tsconfig.json'

350

}

351

}

352

});

353

```

354

355

## Running Type Tests

356

357

Type tests are checked during regular test runs, or can be run separately:

358

359

```bash

360

# Run all tests including type tests

361

vitest

362

363

# Run only type tests

364

vitest typecheck

365

```

366

367

## Common Patterns

368

369

### Testing API Return Types

370

371

```typescript

372

import { test, expectTypeOf } from 'vitest';

373

374

test('API types', () => {

375

async function fetchUser(id: number): Promise<{

376

id: number;

377

name: string;

378

email: string;

379

}> {

380

// implementation

381

}

382

383

expectTypeOf(fetchUser).parameter(0).toBeNumber();

384

expectTypeOf(fetchUser).returns.resolves.toMatchTypeOf<{

385

id: number;

386

name: string;

387

email: string;

388

}>();

389

});

390

```

391

392

### Testing Type Narrowing

393

394

```typescript

395

import { test, expectTypeOf, assertType } from 'vitest';

396

397

test('type narrowing', () => {

398

function process(value: string | number) {

399

if (typeof value === 'string') {

400

assertType<string>(value);

401

expectTypeOf(value).toBeString();

402

} else {

403

assertType<number>(value);

404

expectTypeOf(value).toBeNumber();

405

}

406

}

407

});

408

```

409

410

### Testing Generic Constraints

411

412

```typescript

413

import { test, expectTypeOf } from 'vitest';

414

415

test('generic constraints', () => {

416

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {

417

return obj[key];

418

}

419

420

type User = { name: string; age: number };

421

const user: User = { name: 'John', age: 30 };

422

423

expectTypeOf(getProperty(user, 'name')).toBeString();

424

expectTypeOf(getProperty(user, 'age')).toBeNumber();

425

});

426

```

427

428

## Type Definitions

429

430

```typescript { .api }

431

type ExpectTypeOf<T> = {

432

toEqualTypeOf: <Expected>() => void;

433

toMatchTypeOf: <Expected>() => void;

434

toBeAny: () => void;

435

toBeUnknown: () => void;

436

toBeNever: () => void;

437

toBeFunction: () => void;

438

toBeObject: () => void;

439

toBeArray: () => void;

440

toBeString: () => void;

441

toBeNumber: () => void;

442

toBeBoolean: () => void;

443

toBeVoid: () => void;

444

toBeNull: () => void;

445

toBeUndefined: () => void;

446

toBeNullable: () => void;

447

toBeCallableWith: (...args: any[]) => void;

448

toBeConstructibleWith: (...args: any[]) => void;

449

toHaveProperty: <K extends keyof T>(key: K) => ExpectTypeOf<T[K]>;

450

not: ExpectTypeOf<T>;

451

resolves: T extends Promise<infer U> ? ExpectTypeOf<U> : never;

452

parameters: T extends (...args: infer P) => any ? ExpectTypeOf<P> : never;

453

returns: T extends (...args: any[]) => infer R ? ExpectTypeOf<R> : never;

454

items: T extends (infer Item)[] ? ExpectTypeOf<Item> : never;

455

};

456

457

type AssertType = <T>(value: T) => void;

458

```

459