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 test
yarn test
pnpm run test
bun test
A 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.