Típusok Tesztelése
Példa Projekt
A Vitest lehetővé teszi, hogy teszteket írj a típusaidhoz, az expectTypeOf vagy assertType szintaxisok használatával. Alapértelmezetten minden *.test-d.ts fájlban lévő teszt típus tesztnek számít, de ezt megváltoztathatod a typecheck.include konfigurációs opcióval.
A Vitest a háttérben a tsc vagy vue-tsc parancsot futtatja, a konfigurációdtól függően, és elemzi az eredményeket. A Vitest kiírja a forráskódban található típushibákat is, ha talál ilyet. Ezt letilthatod a typecheck.ignoreSourceErrors konfigurációs opcióval.
Ne feledd, hogy a Vitest nem futtatja ezeket a fájlokat; azokat csak a fordítóprogram elemzi statikusan. Ez azt jelenti, hogy ha dinamikus nevet, test.each vagy test.for metódust használsz, a teszt neve nem lesz kiértékelve – úgy jelenik meg, ahogy van.
WARNING
A Vitest 2.1 előtt a typecheck.include felülírta az include mintát, így a futásidejű tesztjeid valójában nem futottak; csak típusellenőrzésen estek át.
A Vitest 2.1 óta, ha az include és a typecheck.include átfedésben van, a Vitest külön bejegyzésként jelenti a típus teszteket és a futásidejű teszteket.
A CLI flag-ek, mint például a --allowOnly és a -t szintén támogatottak a típusellenőrzéshez.
import { assertType, expectTypeOf } from 'vitest';
import { mount } from './mount.js';
test('my types work properly', () => {
expectTypeOf(mount).toBeFunction();
expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
// @ts-expect-error name is a string
assertType(mount({ name: 42 }));
});Bármely tesztfájlban kiváltott típushiba teszthibaként kerül kezelésre, így bármilyen típusellenőrzési technikát használhatsz a projekted típusainak teszteléséhez.
A lehetséges illesztők listáját az API szekcióban találod.
Hibák Olvasása
Ha az expectTypeOf API-t használod, tekintsd meg az expect-type dokumentációját a hibaüzeneteiről.
Amikor a típusok nem egyeznek, a .toEqualTypeOf és .toMatchTypeOf egy speciális segédtípust használ, hogy a lehető leginkább hasznos hibaüzeneteket állítsa elő. De van egy kis finomság a megértésükben. Mivel az állítások "fluent" stílusban vannak megírva, a hiba az "elvárt" típuson kell, hogy legyen, nem a "tényleges" típuson (expect<Actual>().toEqualTypeOf<Expected>()). Ezért a típushibák zavaróak lehetnek – ezért ez a könyvtár egy MismatchInfo típust hoz létre, hogy megpróbálja explicit módon megfogalmazni, mi az elvárás. Például:
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();Ez az állítás hibát fog okozni, mivel az {a: 1} típusa {a: number} és nem {a: string}. A hibaüzenet ebben az esetben valami ilyesmi lesz:
test/test.ts:999:999 - error TS2344: Type '{ a: string; }' does not satisfy the constraint '{ a: \\"Expected: string, Actual: number\\"; }'.
Types of property 'a' are incompatible.
Type 'string' is not assignable to type '\\"Expected: string, Actual: number\\"'.
999 expectTypeOf({a: 1}).toEqualTypeOf<{a: string}>()Figyeld meg, hogy a jelentett típusmegkötés egy jól olvasható üzenet, amely mind az "elvárt", mind a "tényleges" típusokat megadja. Ahelyett, hogy szó szerint vennéd a mondatot: Types of property 'a' are incompatible // Type 'string' is not assignable to type "Expected: string, Actual: number", csak nézd meg a tulajdonság nevét ('a') és az üzenetet: Expected: string, Actual: number. Ez a legtöbb esetben jelzi, mi a probléma. A rendkívül komplex típusok természetesen több erőfeszítést igényelnek a hibakereséshez, és némi kísérletezést is igényelhetnek. Kérjük, jelentsen be egy hibát, ha a hibaüzenetek valójában félrevezetőek.
A toBe... metódusok (mint például toBeString, toBeNumber, toBeVoid stb.) úgy hibáznak, hogy nem hívható típusra oldódnak fel, ha a tesztelt Actual típus nem egyezik. Például, egy olyan állítás hibája, mint az expectTypeOf(1).toBeString() valami ilyesmi lesz:
test/test.ts:999:999 - error TS2349: This expression is not callable.
Type 'ExpectString<number>' has no call signatures.
999 expectTypeOf(1).toBeString()
~~~~~~~~~~A This expression is not callable rész nem túl hasznos – a lényeges hiba a következő sor: Type 'ExpectString<number>' has no call signatures. Ez lényegében azt jelenti, hogy számot adtál át, de azt állítottad, hogy stringnek kellene lennie.
Ha a TypeScript támogatná a "throw" típusokat, ezek a hibaüzenetek jelentősen javulhatnak. Addig is némi alaposabb áttekintést igényelnek.
Konkrét "elvárt" objektumok vs. típusargumentumok
Az ilyen állítások hibaüzenetei:
expectTypeOf({ a: 1 }).toEqualTypeOf({ a: '' });Kevésbé hasznosak lesznek, mint az ilyen állításoké:
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();Ez azért van, mert a TypeScript fordítónak ki kell következtetnie a típusargumentumot a .toEqualTypeOf({a: ''}) stílushoz, és ez a könyvtár csak egy általános Mismatch típussal való összehasonlítással tudja hibaként megjelölni. Tehát, ahol lehetséges, használj típusargumentumot a konkrét típus helyett a .toEqualTypeOf és toMatchTypeOf esetében. Ha sokkal kényelmesebb két konkrét típust összehasonlítani, használhatod a typeof operátort:
const one = valueFromFunctionOne({ some: { complex: inputs } });
const two = valueFromFunctionTwo({ some: { other: inputs } });
expectTypeOf(one).toEqualTypeOf<typeof two>();Ha nehéznek találod az expectTypeOf API-val való munkát és a hibák megértését, mindig használhatod az egyszerűbb assertType API-t:
const answer = 42;
assertType<number>(answer);
// @ts-expect-error answer is not a string
assertType<string>(answer);TIP
Az @ts-expect-error szintaxis használatakor érdemes meggyőződni arról, hogy nem írtál el semmit. Ezt úgy teheted meg, hogy a típusfájljaidat belefoglalod a test.include konfigurációs opcióba, így a Vitest ténylegesen futtatni fogja ezeket a teszteket, és ReferenceError hibát fog jelezni.
Ez a teszt sikeres lesz, mert hibát vár, de az “answer” szó el van írva, így ez egy téves pozitív hiba:
// @ts-expect-error answer is not a string
assertType<string>(answr);Típusellenőrzés Futtatása
A típusellenőrzés engedélyezéséhez egyszerűen add hozzá a --typecheck flaget a Vitest parancsodhoz a package.json fájlban:
{
"scripts": {
"test": "vitest --typecheck"
}
}Most már futtathatod a típusellenőrzést:
npm run testyarn testpnpm run testbun testA Vitest a tsc --noEmit vagy vue-tsc --noEmit parancsot használja, a konfigurációdtól függően, így ezeket a szkripteket eltávolíthatod a build folyamatodból.