Skip to content

expectTypeOf

WARNING

在运行时,此函数不执行任何操作。要 启用类型检查,别忘了传递 --typecheck 标志。

  • 类型: <T>(a: unknown) => ExpectTypeOf

not

  • 类型: ExpectTypeOf

你可以使用 .not 属性来否定所有断言。

toEqualTypeOf

  • 类型: <T>(expected: T) => void

此匹配器将检查类型是否完全相等。如果两个对象具有不同的值但类型相同,此匹配器不会失败。但是,如果对象缺少属性,它将失败。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number }>()
expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 1 })
expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 2 })
expectTypeOf({ a: 1, b: 1 }).not.toEqualTypeOf<{ a: number }>()

toMatchTypeOf

  • 类型: <T>(expected: T) => void

已弃用

此匹配器自 expect-type v1.2.0 起已弃用。请改用 toExtend

此匹配器检查期望类型是否扩展了提供的类型。它与 toEqual 不同,更类似于 expect 的 toMatchObject()。使用此匹配器,你可以检查对象是否“匹配”类型。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf({ a: 1 })
expectTypeOf<number>().toMatchTypeOf<string | number>()
expectTypeOf<string | number>().not.toMatchTypeOf<number>()

toExtend

  • 类型: <T>(expected: T) => void

此匹配器检查期望类型是否扩展了提供的类型。它与 toEqual 不同,更类似于 expect 的 toMatchObject()。使用此匹配器,你可以检查对象是否“匹配”类型。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf({ a: 1, b: 1 }).toExtend({ a: 1 })
expectTypeOf<number>().toExtend<string | number>()
expectTypeOf<string | number>().not.toExtend<number>()

toMatchObjectType

  • 类型: () => void

此匹配器对对象类型执行严格检查,确保期望类型与提供的对象类型匹配。它比 toExtend 更严格,并且是处理对象类型时的推荐选择,因为它更有可能捕获诸如只读属性之类的问题。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf({ a: 1, b: 2 }).toMatchObjectType<{ a: number }>() // 首选
expectTypeOf({ a: 1, b: 2 }).toExtend<{ a: number }>() // 有效但不够严格

// 支持嵌套对象检查
const user = {
  name: 'John',
  address: { city: 'New York', zip: '10001' }
}
expectTypeOf(user).toMatchObjectType<{ name: string; address: { city: string } }>()

WARNING

此匹配器仅适用于普通对象类型。对于联合类型和其他复杂类型,它将失败。对于这些情况,请改用 toExtend

extract

  • 类型: ExpectTypeOf<ExtractedUnion>

你可以使用 .extract 来缩小类型范围以进行进一步测试。

ts
import { expectTypeOf } from 'vitest'

type ResponsiveProp<T> = T | T[] | { xs?: T; sm?: T; md?: T }

interface CSSProperties { margin?: string; padding?: string }

function getResponsiveProp<T>(_props: T): ResponsiveProp<T> {
  return {}
}

const cssProperties: CSSProperties = { margin: '1px', padding: '2px' }

expectTypeOf(getResponsiveProp(cssProperties))
  .extract<{ xs?: any }>() // 从联合类型中提取最后一个类型
  .toEqualTypeOf<{ xs?: CSSProperties; sm?: CSSProperties; md?: CSSProperties }>()

expectTypeOf(getResponsiveProp(cssProperties))
  .extract<unknown[]>() // 从联合类型中提取数组
  .toEqualTypeOf<CSSProperties[]>()

WARNING

如果在联合类型中未找到类型,.extract 将返回 never

exclude

  • 类型: ExpectTypeOf<NonExcludedUnion>

你可以使用 .exclude 从联合类型中移除类型以进行进一步测试。

ts
import { expectTypeOf } from 'vitest'

type ResponsiveProp<T> = T | T[] | { xs?: T; sm?: T; md?: T }

interface CSSProperties { margin?: string; padding?: string }

function getResponsiveProp<T>(_props: T): ResponsiveProp<T> {
  return {}
}

const cssProperties: CSSProperties = { margin: '1px', padding: '2px' }

expectTypeOf(getResponsiveProp(cssProperties))
  .exclude<unknown[]>()
  .exclude<{ xs?: unknown }>() // 或者直接使用 .exclude<unknown[] | { xs?: unknown }>()
  .toEqualTypeOf<CSSProperties>()

WARNING

如果在联合类型中未找到类型,.exclude 将返回 never

returns

  • 类型: ExpectTypeOf<ReturnValue>

你可以使用 .returns 提取函数类型的返回值。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(() => {}).returns.toBeVoid()
expectTypeOf((a: number) => [a, a]).returns.toEqualTypeOf([1, 2])

WARNING

如果用于非函数类型,它将返回 never,因此你将无法将其与其他匹配器链式调用。

parameters

  • 类型: ExpectTypeOf<Parameters>

你可以使用 .parameters 提取函数参数以对其值执行断言。参数作为数组返回。

ts
import { expectTypeOf } from 'vitest'

type NoParam = () => void
type HasParam = (s: string) => void

expectTypeOf<NoParam>().parameters.toEqualTypeOf<[]>()
expectTypeOf<HasParam>().parameters.toEqualTypeOf<[string]>()

WARNING

如果用于非函数类型,它将返回 never,因此你将无法将其与其他匹配器链式调用。

TIP

你也可以使用 .toBeCallableWith 匹配器作为更具表现力的断言。

parameter

  • 类型: (nth: number) => ExpectTypeOf

你可以使用 .parameter(number) 调用提取特定的函数参数以对其执行其他断言。

ts
import { expectTypeOf } from 'vitest'

function foo(a: number, b: string) {
  return [a, b]
}

expectTypeOf(foo).parameter(0).toBeNumber()
expectTypeOf(foo).parameter(1).toBeString()

WARNING

如果用于非函数类型,它将返回 never,因此你将无法将其与其他匹配器链式调用。

constructorParameters

  • 类型: ExpectTypeOf<ConstructorParameters>

你可以使用此方法将构造函数参数提取为值数组并对它们执行断言。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(Date).constructorParameters.toEqualTypeOf<[] | [string | number | Date]>()

WARNING

如果用于非函数类型,它将返回 never,因此你将无法将其与其他匹配器链式调用。

TIP

你也可以使用 .toBeConstructibleWith 匹配器作为更具表现力的断言。

instance

  • 类型: ExpectTypeOf<ConstructableInstance>

此属性允许访问可在所提供类的实例上执行的匹配器。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(Date).instance.toHaveProperty('toISOString')

WARNING

如果用于非函数类型,它将返回 never,因此你将无法将其与其他匹配器链式调用。

items

  • 类型: ExpectTypeOf<T>

你可以使用 .items 获取数组项类型以执行进一步断言。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf([1, 2, 3]).items.toEqualTypeOf<number>()
expectTypeOf([1, 2, 3]).items.not.toEqualTypeOf<string>()

resolves

  • 类型: ExpectTypeOf<ResolvedPromise>

此匹配器提取 Promise 的解析值,以便你可以对其执行其他断言。

ts
import { expectTypeOf } from 'vitest'

async function asyncFunc() {
  return 123
}

expectTypeOf(asyncFunc).returns.resolves.toBeNumber()
expectTypeOf(Promise.resolve('string')).resolves.toBeString()

WARNING

如果用于非 Promise 类型,它将返回 never,因此你将无法将其与其他匹配器链式调用。

guards

  • 类型: ExpectTypeOf<Guard>

此匹配器提取守卫值(例如,v is number),以便你可以对其执行断言。

ts
import { expectTypeOf } from 'vitest'

function isString(v: any): v is string {
  return typeof v === 'string'
}
expectTypeOf(isString).guards.toBeString()

WARNING

如果值不是守卫函数,则返回 never,因此你将无法将其与其他匹配器链式调用。

asserts

  • 类型: ExpectTypeOf<Assert>

此匹配器提取断言值(例如,assert v is number),以便你可以对其执行断言。

ts
import { expectTypeOf } from 'vitest'

function assertNumber(v: any): asserts v is number {
  if (typeof v !== 'number') {
    throw new TypeError('Nope !')
  }
}

expectTypeOf(assertNumber).asserts.toBeNumber()

WARNING

如果值不是断言函数,则返回 never,因此你将无法将其与其他匹配器链式调用。

toBeAny

  • 类型: () => void

使用此匹配器,你可以检查提供的类型是否为 any 类型。如果类型太具体,测试将失败。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf<any>().toBeAny()
expectTypeOf({} as any).toBeAny()
expectTypeOf('string').not.toBeAny()

toBeUnknown

  • 类型: () => void

此匹配器检查提供的类型是否为 unknown 类型。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf().toBeUnknown()
expectTypeOf({} as unknown).toBeUnknown()
expectTypeOf('string').not.toBeUnknown()

toBeNever

  • 类型: () => void

此匹配器检查提供的类型是否为 never 类型。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf<never>().toBeNever()
expectTypeOf((): never => {}).returns.toBeNever()

toBeFunction

  • 类型: () => void

此匹配器检查提供的类型是否为 function

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(42).not.toBeFunction()
expectTypeOf((): never => {}).toBeFunction()

toBeObject

  • 类型: () => void

此匹配器检查提供的类型是否为 object

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(42).not.toBeObject()
expectTypeOf({}).toBeObject()

toBeArray

  • 类型: () => void

此匹配器检查提供的类型是否为 Array<T>

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(42).not.toBeArray()
expectTypeOf([]).toBeArray()
expectTypeOf([1, 2]).toBeArray()
expectTypeOf([{}, 42]).toBeArray()

toBeString

  • Type: () => void

此匹配器检查提供的类型是否为 string

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(42).not.toBeString()
expectTypeOf('').toBeString()
expectTypeOf('a').toBeString()

toBeBoolean

  • Type: () => void

此匹配器检查提供的类型是否为 boolean

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(42).not.toBeBoolean()
expectTypeOf(true).toBeBoolean()
expectTypeOf<boolean>().toBeBoolean()

toBeVoid

  • Type: () => void

此匹配器检查提供的类型是否为 void

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(() => {}).returns.toBeVoid()
expectTypeOf<void>().toBeVoid()

toBeSymbol

  • Type: () => void

此匹配器检查提供的类型是否为 symbol

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(Symbol(1)).toBeSymbol()
expectTypeOf<symbol>().toBeSymbol()

toBeNull

  • Type: () => void

此匹配器检查提供的类型是否为 null

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(null).toBeNull()
expectTypeOf<null>().toBeNull()
expectTypeOf(undefined).not.toBeNull()

toBeUndefined

  • Type: () => void

此匹配器检查提供的类型是否为 undefined

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(undefined).toBeUndefined()
expectTypeOf<undefined>().toBeUndefined()
expectTypeOf(null).not.toBeUndefined()

toBeNullable

  • Type: () => void

此匹配器检查是否可以将 nullundefined 用于提供的类型。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf<undefined | 1>().toBeNullable()
expectTypeOf<null | 1>().toBeNullable()
expectTypeOf<undefined | null | 1>().toBeNullable()

toBeCallableWith

  • Type: () => void

此匹配器确保你可以使用一组参数调用提供的函数。

ts
import { expectTypeOf } from 'vitest'

type NoParam = () => void
type HasParam = (s: string) => void

expectTypeOf<NoParam>().toBeCallableWith()
expectTypeOf<HasParam>().toBeCallableWith('some string')

WARNING

如果在非函数类型上使用,它将返回 never,因此你将无法将其与其他匹配器链式调用。

toBeConstructibleWith

  • Type: () => void

此匹配器确保你可以使用一组构造函数参数创建新实例。

ts
import { expectTypeOf } from 'vitest'

expectTypeOf(Date).toBeConstructibleWith(new Date())
expectTypeOf(Date).toBeConstructibleWith('01-01-2000')

WARNING

如果在非函数类型上使用,它将返回 never,因此你将无法将其与其他匹配器链式调用。

toHaveProperty

  • Type: <K extends keyof T>(property: K) => ExpectTypeOf<T[K]

此匹配器检查提供的对象上是否存在属性。如果存在,它还会为该属性的类型返回同一组匹配器,因此你可以依次链式调用断言。

ts
import { expectTypeOf } from 'vitest'

const obj = { a: 1, b: '' }

expectTypeOf(obj).toHaveProperty('a')
expectTypeOf(obj).not.toHaveProperty('c')

expectTypeOf(obj).toHaveProperty('a').toBeNumber()
expectTypeOf(obj).toHaveProperty('b').toBeString()
expectTypeOf(obj).toHaveProperty('a').not.toBeString()

branded

  • Type: ExpectTypeOf<BrandedType>

你可以使用 .branded 来允许类型断言在类型语义等价但表示形式不同的情况下成功。

ts
import { expectTypeOf } from 'vitest'

// 如果没有 .branded,即使类型实际上相同,这也会失败
expectTypeOf<{ a: { b: 1 } & { c: 1 } }>().toEqualTypeOf<{ a: { b: 1; c: 1 } }>()

// 使用 .branded,断言成功
expectTypeOf<{ a: { b: 1 } & { c: 1 } }>().branded.toEqualTypeOf<{ a: { b: 1; c: 1 } }>()

WARNING

此辅助工具会带来性能开销,如果与过深的类型一起使用,可能会导致 TypeScript 编译器“放弃”。请谨慎使用,仅在必要时使用。