[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

feat: support `expect.assert` for type narrowing (#8695)

authored by

Vladimir and committed by
GitHub
(Oct 12, 2025, 1:06 PM +0200) fe5895d2 699bf804

+45 -13
+13 -13
docs/api/assert.md
··· 35 35 36 36 ## isOk 37 37 38 - - **Type:** `<T>(value: T, message?: string) => void` 38 + - **Type:** `<T>(value: T, message?: string) => asserts value` 39 39 - **Alias** `ok` 40 40 41 41 Assert that the given `value` is truthy. ··· 195 195 196 196 ## isTrue 197 197 198 - - **Type:** `<T>(value: T, message?: string) => void` 198 + - **Type:** `<T>(value: T, message?: string) => asserts value is true` 199 199 200 200 Asserts that `value` is true. 201 201 ··· 211 211 212 212 ## isNotTrue 213 213 214 - - **Type:** `<T>(value: T, message?: string) => void` 214 + - **Type:** `<T>(value: T, message?: string) => asserts value is Exclude<T, true>` 215 215 216 216 Asserts that `value` is not true. 217 217 ··· 227 227 228 228 ## isFalse 229 229 230 - - **Type:** `<T>(value: T, message?: string) => void` 230 + - **Type:** `<T>(value: T, message?: string) => asserts value is false` 231 231 232 232 Asserts that `value` is false. 233 233 ··· 243 243 244 244 ## isNotFalse 245 245 246 - - **Type:** `<T>(value: T, message?: string) => void` 246 + - **Type:** `<T>(value: T, message?: string) => asserts value is Exclude<T, false>` 247 247 248 248 Asserts that `value` is not false. 249 249 ··· 259 259 260 260 ## isNull 261 261 262 - - **Type:** `<T>(value: T, message?: string) => void` 262 + - **Type:** `<T>(value: T, message?: string) => asserts value is null` 263 263 264 264 Asserts that `value` is null. 265 265 ··· 275 275 276 276 ## isNotNull 277 277 278 - - **Type:** `<T>(value: T, message?: string) => void` 278 + - **Type:** `<T>(value: T, message?: string) => asserts value is Exclude<T, null>` 279 279 280 280 Asserts that `value` is not null. 281 281 ··· 323 323 324 324 ## exists 325 325 326 - - **Type:** `<T>(value: T, message?: string) => void` 326 + - **Type:** `<T>(value: T, message?: string) => asserts value is NonNullable<T>` 327 327 328 328 Asserts that `value` is neither null nor undefined. 329 329 ··· 339 339 340 340 ## notExists 341 341 342 - - **Type:** `<T>(value: T, message?: string) => void` 342 + - **Type:** `<T>(value: T, message?: string) => asserts value is null | undefined` 343 343 344 344 Asserts that `value` is either null nor undefined. 345 345 ··· 357 357 358 358 ## isUndefined 359 359 360 - - **Type:** `<T>(value: T, message?: string) => void` 360 + - **Type:** `<T>(value: T, message?: string) => asserts value is undefined` 361 361 362 362 Asserts that `value` is undefined. 363 363 ··· 373 373 374 374 ## isDefined 375 375 376 - - **Type:** `<T>(value: T, message?: string) => void` 376 + - **Type:** `<T>(value: T, message?: string) => asserts value is Exclude<T, undefined>` 377 377 378 378 Asserts that `value` is not undefined. 379 379 ··· 631 631 632 632 ## instanceOf 633 633 634 - - **Type:** `<T>(value: T, constructor: Function, message?: string) => void` 634 + - **Type:** `<T>(value: T, constructor: Function, message?: string) => asserts value is T` 635 635 636 636 Asserts that `value` is an instance of `constructor`. 637 637 ··· 656 656 657 657 ## notInstanceOf 658 658 659 - - **Type:** `<T>(value: T, constructor: Function, message?: string) => void` 659 + - **Type:** `<T>(value: T, constructor: Function, message?: string) => asserts value is Exclude<T, U>` 660 660 661 661 Asserts that `value` is not an instance of `constructor`. 662 662
+30
docs/api/expect.md
··· 39 39 `expect` has no effect on testing types, if the expression doesn't have a type error. If you want to use Vitest as [type checker](/guide/testing-types), use [`expectTypeOf`](/api/expect-typeof) or [`assertType`](/api/assert-type). 40 40 ::: 41 41 42 + ## assert 43 + 44 + - **Type:** `Chai.AssertStatic` 45 + 46 + Vitest reexports chai's [`assert` API](https://www.chaijs.com/api/assert/) as `expect.assert` for convenience. You can see the supported methods on the [Assert API page](/api/assert). 47 + 48 + This is especially useful if you need to narrow down the type, since `expect.to*` methods do not support that: 49 + 50 + ```ts 51 + interface Cat { 52 + __type: 'Cat' 53 + mew(): void 54 + } 55 + interface Dog { 56 + __type: 'Dog' 57 + bark(): void 58 + } 59 + type Animal = Cat | Dog 60 + 61 + const animal: Animal = { __type: 'Dog', bark: () => {} } 62 + 63 + expect.assert(animal.__type === 'Dog') 64 + // does not show a type error! 65 + expect(animal.bark()).toBeUndefined() 66 + ``` 67 + 68 + ::: tip 69 + Note that `expect.assert` also supports other type-narrowing methods (like `assert.isDefined`, `assert.exists` and so on). 70 + ::: 71 + 42 72 ## soft 43 73 44 74 - **Type:** `ExpectStatic & (actual: any) => Assertions`
+1
packages/vitest/src/types/global.ts
··· 34 34 } 35 35 36 36 interface ExpectStatic { 37 + assert: Chai.AssertStatic 37 38 unreachable: (message?: string) => never 38 39 soft: <T>(actual: T, message?: string) => Assertion<T> 39 40 poll: <T>(
+1
packages/vitest/src/integrations/chai/index.ts
··· 57 57 expect, 58 58 ) 59 59 60 + expect.assert = chai.assert 60 61 // @ts-expect-error untyped 61 62 expect.extend = matchers => chai.expect.extend(expect, matchers) 62 63 expect.addEqualityTesters = customTesters =>