--- url: /api/expect-typeof.md --- # expectTypeOf ::: warning 在运行时,此函数不执行任何操作。要 [启用类型检查](/guide/testing-types#run-typechecking),别忘了传递 `--typecheck` 标志。 ::: * **类型:** `(a: unknown) => ExpectTypeOf` ## not * **类型:** `ExpectTypeOf` 你可以使用 `.not` 属性来否定所有断言。 ## toEqualTypeOf * **类型:** `(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 * **类型:** `(expected: T) => void` ::: warning 已弃用 此匹配器自 expect-type v1.2.0 起已弃用。请改用 [`toExtend`](#toextend)。 ::: 此匹配器检查期望类型是否扩展了提供的类型。它与 `toEqual` 不同,更类似于 [expect 的](/api/expect) `toMatchObject()`。使用此匹配器,你可以检查对象是否“匹配”类型。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf({ a: 1 }) expectTypeOf().toMatchTypeOf() expectTypeOf().not.toMatchTypeOf() ``` ## toExtend * **类型:** `(expected: T) => void` 此匹配器检查期望类型是否扩展了提供的类型。它与 `toEqual` 不同,更类似于 [expect 的](/api/expect) `toMatchObject()`。使用此匹配器,你可以检查对象是否“匹配”类型。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf({ a: 1, b: 1 }).toExtend({ a: 1 }) expectTypeOf().toExtend() expectTypeOf().not.toExtend() ``` ## toMatchObjectType * **类型:** `() => void` 此匹配器对对象类型执行严格检查,确保期望类型与提供的对象类型匹配。它比 [`toExtend`](#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`](#toextend)。 ::: ## extract * **类型:** `ExpectTypeOf` 你可以使用 `.extract` 来缩小类型范围以进行进一步测试。 ```ts import { expectTypeOf } from 'vitest' type ResponsiveProp = T | T[] | { xs?: T; sm?: T; md?: T } interface CSSProperties { margin?: string; padding?: string } function getResponsiveProp(_props: T): ResponsiveProp { 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() // 从联合类型中提取数组 .toEqualTypeOf() ``` ::: warning 如果在联合类型中未找到类型,`.extract` 将返回 `never`。 ::: ## exclude * **类型:** `ExpectTypeOf` 你可以使用 `.exclude` 从联合类型中移除类型以进行进一步测试。 ```ts import { expectTypeOf } from 'vitest' type ResponsiveProp = T | T[] | { xs?: T; sm?: T; md?: T } interface CSSProperties { margin?: string; padding?: string } function getResponsiveProp(_props: T): ResponsiveProp { return {} } const cssProperties: CSSProperties = { margin: '1px', padding: '2px' } expectTypeOf(getResponsiveProp(cssProperties)) .exclude() .exclude<{ xs?: unknown }>() // 或者直接使用 .exclude() .toEqualTypeOf() ``` ::: warning 如果在联合类型中未找到类型,`.exclude` 将返回 `never`。 ::: ## returns * **类型:** `ExpectTypeOf` 你可以使用 `.returns` 提取函数类型的返回值。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf(() => {}).returns.toBeVoid() expectTypeOf((a: number) => [a, a]).returns.toEqualTypeOf([1, 2]) ``` ::: warning 如果用于非函数类型,它将返回 `never`,因此你将无法将其与其他匹配器链式调用。 ::: ## parameters * **类型:** `ExpectTypeOf` 你可以使用 `.parameters` 提取函数参数以对其值执行断言。参数作为数组返回。 ```ts import { expectTypeOf } from 'vitest' type NoParam = () => void type HasParam = (s: string) => void expectTypeOf().parameters.toEqualTypeOf<[]>() expectTypeOf().parameters.toEqualTypeOf<[string]>() ``` ::: warning 如果用于非函数类型,它将返回 `never`,因此你将无法将其与其他匹配器链式调用。 ::: ::: tip 你也可以使用 [`.toBeCallableWith`](#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` 你可以使用此方法将构造函数参数提取为值数组并对它们执行断言。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf(Date).constructorParameters.toEqualTypeOf<[] | [string | number | Date]>() ``` ::: warning 如果用于非函数类型,它将返回 `never`,因此你将无法将其与其他匹配器链式调用。 ::: ::: tip 你也可以使用 [`.toBeConstructibleWith`](#tobeconstructiblewith) 匹配器作为更具表现力的断言。 ::: ## instance * **类型:** `ExpectTypeOf` 此属性允许访问可在所提供类的实例上执行的匹配器。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf(Date).instance.toHaveProperty('toISOString') ``` ::: warning 如果用于非函数类型,它将返回 `never`,因此你将无法将其与其他匹配器链式调用。 ::: ## items * **类型:** `ExpectTypeOf` 你可以使用 `.items` 获取数组项类型以执行进一步断言。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf([1, 2, 3]).items.toEqualTypeOf() expectTypeOf([1, 2, 3]).items.not.toEqualTypeOf() ``` ## resolves * **类型:** `ExpectTypeOf` 此匹配器提取 `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` 此匹配器提取守卫值(例如,`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 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().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().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`。 ```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().toBeBoolean() ``` ## toBeVoid * **Type:** `() => void` 此匹配器检查提供的类型是否为 `void`。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf(() => {}).returns.toBeVoid() expectTypeOf().toBeVoid() ``` ## toBeSymbol * **Type:** `() => void` 此匹配器检查提供的类型是否为 `symbol`。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf(Symbol(1)).toBeSymbol() expectTypeOf().toBeSymbol() ``` ## toBeNull * **Type:** `() => void` 此匹配器检查提供的类型是否为 `null`。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf(null).toBeNull() expectTypeOf().toBeNull() expectTypeOf(undefined).not.toBeNull() ``` ## toBeUndefined * **Type:** `() => void` 此匹配器检查提供的类型是否为 `undefined`。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf(undefined).toBeUndefined() expectTypeOf().toBeUndefined() expectTypeOf(null).not.toBeUndefined() ``` ## toBeNullable * **Type:** `() => void` 此匹配器检查是否可以将 `null` 或 `undefined` 用于提供的类型。 ```ts import { expectTypeOf } from 'vitest' expectTypeOf().toBeNullable() expectTypeOf().toBeNullable() expectTypeOf().toBeNullable() ``` ## toBeCallableWith * **Type:** `() => void` 此匹配器确保你可以使用一组参数调用提供的函数。 ```ts import { expectTypeOf } from 'vitest' type NoParam = () => void type HasParam = (s: string) => void expectTypeOf().toBeCallableWith() expectTypeOf().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:** `(property: K) => ExpectTypeOf` 你可以使用 `.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 编译器“放弃”。请谨慎使用,仅在必要时使用。 :::