-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Add Vitest integration for type-testing #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /** | ||
| * Vitest integration for type-testing. | ||
| * | ||
| * @packageDocumentation | ||
| */ | ||
|
|
||
| export { | ||
| toBeType, | ||
| toNotBeType, | ||
| toExtend, | ||
| toNotExtend, | ||
| toHaveProperty, | ||
| toBeAny, | ||
| toBeNever, | ||
| toBeUnknown, | ||
| toBeVoid, | ||
| toBeUndefined, | ||
| toBeNull, | ||
| toBeNullable, | ||
| toBeOptional, | ||
| toBeUnion, | ||
| toBeTuple, | ||
| toBeArray, | ||
| toBeInhabited, | ||
| toBeUninhabited, | ||
| expectType | ||
| } from './matchers.js' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| /** | ||
| * Custom Vitest matchers for type testing. | ||
| * | ||
| * These matchers provide compile-time type checking. At runtime, they return | ||
| * undefined to allow the test to pass. The actual type checking happens | ||
| * at compile time through TypeScript's type system. | ||
| */ | ||
|
|
||
| import type { Equal, NotEqual } from '../types/equality.js' | ||
| import type { IsAny, IsNever, IsUnknown, IsVoid, IsUndefined, IsNull, IsNullable, IsOptional } from '../types/special.js' | ||
| import type { IsUnion, IsTuple, IsArray } from '../types/union.js' | ||
| import type { IsInhabited, IsUninhabited } from '../types/inhabitation.js' | ||
| import type { HasProperty } from '../types/property.js' | ||
| import type { CheckPass } from '../api/check.js' | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for type equality. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * import { expect, test } from 'vitest' | ||
| * import { toBeType } from '@deessejs/type-testing/vitest' | ||
| * | ||
| * expect.extend({ toBeType }) | ||
| * | ||
| * test('type check', () => { | ||
| * expectType<string>().toBeType<string>() | ||
| * }) | ||
| * ``` | ||
| */ | ||
| export function toBeType<T, U>(): Equal<T, U> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for type inequality. | ||
| */ | ||
| export function toNotBeType<T, U>(): NotEqual<T, U> extends true ? CheckPass : never { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This matcher follows a different naming convention than standard Jest/Vitest matchers which typically use |
||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for type extends check. | ||
| */ | ||
| export function toExtend<T, U>(): T extends U ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for type not extends check. | ||
| */ | ||
| export function toNotExtend<T, U>(): T extends U ? never : CheckPass { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for property existence. | ||
| */ | ||
| export function toHaveProperty<T, K extends keyof T>(): HasProperty<T, K> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for any type check. | ||
| */ | ||
| export function toBeAny<T>(): IsAny<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for never type check. | ||
| */ | ||
| export function toBeNever<T>(): IsNever<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for unknown type check. | ||
| */ | ||
| export function toBeUnknown<T>(): IsUnknown<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for void type check. | ||
| */ | ||
| export function toBeVoid<T>(): IsVoid<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for undefined type check. | ||
| */ | ||
| export function toBeUndefined<T>(): IsUndefined<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for null type check. | ||
| */ | ||
| export function toBeNull<T>(): IsNull<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for nullable type check. | ||
| */ | ||
| export function toBeNullable<T>(): IsNullable<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for optional type check. | ||
| */ | ||
| export function toBeOptional<T>(): IsOptional<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for union type check. | ||
| */ | ||
| export function toBeUnion<T>(): IsUnion<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for tuple type check. | ||
| */ | ||
| export function toBeTuple<T>(): IsTuple<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for array type check. | ||
| */ | ||
| export function toBeArray<T>(): IsArray<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for inhabited type check. | ||
| */ | ||
| export function toBeInhabited<T>(): IsInhabited<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Vitest matcher for uninhabited type check. | ||
| */ | ||
| export function toBeUninhabited<T>(): IsUninhabited<T> extends true ? CheckPass : never { | ||
| return undefined as any | ||
| } | ||
|
|
||
| /** | ||
| * Helper function to create a type holder for testing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * expectType<string>().toBeType<string>() | ||
| * ``` | ||
| */ | ||
| export function expectType<T>(): { | ||
| toBeType<U>(): Equal<T, U> extends true ? CheckPass : never | ||
| toNotBeType<U>(): NotEqual<T, U> extends true ? CheckPass : never | ||
| toExtend<U>(): T extends U ? CheckPass : never | ||
| toNotExtend<U>(): T extends U ? never : CheckPass | ||
| toHaveProperty<K extends keyof T>(): HasProperty<T, K> extends true ? CheckPass : never | ||
| toBeAny(): IsAny<T> extends true ? CheckPass : never | ||
| toBeNever(): IsNever<T> extends true ? CheckPass : never | ||
| toBeUnknown(): IsUnknown<T> extends true ? CheckPass : never | ||
| toBeVoid(): IsVoid<T> extends true ? CheckPass : never | ||
| toBeUndefined(): IsUndefined<T> extends true ? CheckPass : never | ||
| toBeNull(): IsNull<T> extends true ? CheckPass : never | ||
| toBeNullable(): IsNullable<T> extends true ? CheckPass : never | ||
| toBeOptional(): IsOptional<T> extends true ? CheckPass : never | ||
| toBeUnion(): IsUnion<T> extends true ? CheckPass : never | ||
| toBeTuple(): IsTuple<T> extends true ? CheckPass : never | ||
| toBeArray(): IsArray<T> extends true ? CheckPass : never | ||
| toBeInhabited(): IsInhabited<T> extends true ? CheckPass : never | ||
| toBeUninhabited(): IsUninhabited<T> extends true ? CheckPass : never | ||
| } { | ||
| return {} as any | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good use of the type holder pattern. The return type casting with |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| /** | ||
| * Vitest setup for type-testing. | ||
| * | ||
| * This module provides integration with Vitest. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // vitest.config.ts | ||
| * import { defineConfig } from 'vitest/config' | ||
| * | ||
| * export default defineConfig({ | ||
| * test: { | ||
| * setupFiles: ['@deessejs/type-testing/vitest/setup'] | ||
| * } | ||
| * }) | ||
| * ``` | ||
| */ | ||
|
|
||
| export { expectType } from './matchers.js' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The setup file exports If the setup file is meant to auto-register matchers, it should include: import { expect } from 'vitest'
import * as matchers from './matchers.js'
expect.extend(matchers)Otherwise, consider clarifying in the documentation that this only exports |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| /** | ||
| * Vitest setup module tests. | ||
| */ | ||
|
|
||
| import { describe, it, expect } from 'vitest' | ||
|
|
||
| // Import from the setup module | ||
| import '../src/vitest/setup' | ||
|
|
||
| describe('Vitest setup', () => { | ||
| it('should export expectType from setup', async () => { | ||
| const { expectType } = await import('../src/vitest/setup') | ||
| expect(expectType).toBeDefined() | ||
| const result = expectType<string>() | ||
| expect(result).toBeDefined() | ||
| }) | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider documenting this new Vitest integration in the README so users know how to use it.