Türleri Test Etme
Örnek Proje
Vitest, expectTypeOf veya assertType sözdizimlerini kullanarak türlerinizi test etmenizi sağlar. Varsayılan olarak *.test-d.ts dosyalarındaki tüm testler tür testleri olarak kabul edilir, ancak bunu typecheck.include yapılandırma seçeneğiyle değiştirebilirsiniz.
Vitest, arka planda yapılandırmanıza bağlı olarak tsc veya vue-tsc'yi çalıştırır ve sonuçları ayrıştırır. Vitest, kaynak kodunuzda herhangi bir tür hatası bulursa bunları da yazdırır. Bu özelliği typecheck.ignoreSourceErrors yapılandırma seçeneğiyle devre dışı bırakabilirsiniz.
Unutmayın, Vitest bu dosyaları çalıştırmaz veya derlemez. Dosyalar yalnızca derleyici tarafından statik olarak analiz edilir. Bu nedenle, dinamik ifadeler kullanamazsınız. Dinamik test adları ve test.each, test.runIf, test.skipIf, test.concurrent API'lerini kullanamazsınız. Ancak test, describe, .only, .skip ve .todo gibi diğer API'leri kullanabilirsiniz.
--allowOnly ve -t gibi CLI bayrakları da tür kontrolü için desteklenir.
import { assertType, expectTypeOf } from 'vitest';
import { mount } from './mount.js';
test('türlerim düzgün çalışıyor', () => {
expectTypeOf(mount).toBeFunction();
expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
// @ts-expect-error name bir string değil
assertType(mount({ name: 42 }));
});Bir test dosyası içinde tetiklenen herhangi bir tür hatası, bir test hatası olarak kabul edilecektir. Bu nedenle, projenizin türlerini test etmek için dilediğiniz yöntemi kullanabilirsiniz.
Olası eşleştiricilerin bir listesini API bölümünde görebilirsiniz.
Hataları Okuma
expectTypeOf API'sini kullanıyorsanız, expect-type'ın hata mesajları hakkındaki belgelerine bakın.
Türler eşleşmediğinde, .toEqualTypeOf ve .toMatchTypeOf, mümkün olduğunca anlaşılır hata mesajları üretmek için özel bir yardımcı tür kullanır. Ancak bunları anlamanın bazı incelikleri vardır. Doğrulamalar zincirleme şekilde yazıldığından, hata "gerçek" türde değil, "beklenen" türde olmalıdır (expect<Actual>().toEqualTypeOf<Expected>()). Bu, tür hatalarının kafa karıştırıcı olabileceği anlamına gelir. Bu nedenle, bu araç, beklentinin ne olduğunu açıkça belirtmek için bir MismatchInfo türü üretir. Örneğin:
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();{a: 1} türü {a: number} olduğundan ve {a: string} olmadığı için başarısız olacak bir iddiadır. Bu durumda hata mesajı şöyle bir şey olacaktır:
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}>()Raporlanan tür kısıtlamasının hem "beklenen" hem de "gerçek" türleri belirten, insanlar tarafından kolayca anlaşılabilir bir mesaj olduğuna dikkat edin. 'a' özelliğinin türleri uyumsuz // 'string' türü "Beklenen: string, Gerçek: number" türüne atanamaz cümlesini kelimenin tam anlamıyla almak yerine, yalnızca özellik adına ('a') ve mesaja bakın: Beklenen: string, Gerçek: number. Bu size çoğu durumda neyin yanlış olduğunu söyleyecektir. Son derece karmaşık türlerin hata ayıklaması elbette daha fazla çaba gerektirecektir ve bazı denemeler gerektirebilir. Hata mesajları aslında yanıltıcıysa lütfen bir sorun bildirin.
toBe... yöntemleri (toBeString, toBeNumber, toBeVoid vb. gibi), test edilen Actual türü eşleşmediğinde çağrılamayan bir türe çözümlenerek başarısız olur. Örneğin, expectTypeOf(1).toBeString() gibi bir iddia için hata şöyle bir şey olacaktır:
test/test.ts:999:999 - error TS2349: This expression is not callable.
Type 'ExpectString<number>' has no call signatures.
999 expectTypeOf(1).toBeString()
~~~~~~~~~~Bu ifade çağrılamaz kısmı pek yardımcı değil. Asıl anlamlı hata bir sonraki satırda: Type 'ExpectString<number> has no call signatures. Bu, aslında bir sayı gönderdiğiniz, ancak bunun bir string olması gerektiğini belirttiğiniz anlamına gelir.
TypeScript "throw" türleri için destek ekleseydi, bu hata mesajları önemli ölçüde iyileştirilebilirdi. O zamana kadar, bu hataları anlamak biraz çaba gerektirecek.
Somut "beklenen" nesneler ve tür argümanları
Şunun gibi bir iddia için hata mesajları:
expectTypeOf({ a: 1 }).toEqualTypeOf({ a: '' });Şunun gibi bir iddia için olduğundan daha az yardımcı olacaktır:
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();Bunun nedeni, TypeScript derleyicisinin .toEqualTypeOf({a: ''}) stili için tür argümanını çıkarması gerekmesidir ve bu araç bunu yalnızca genel bir Mismatch türüne karşı karşılaştırarak bir hata olarak işaretleyebilir. Bu nedenle, mümkün olduğunca .toEqualTypeOf ve toMatchTypeOf için somut bir tür kullanmak yerine, bir tür argümanı kullanın. İki somut türü karşılaştırmak çok daha kolaysa, typeof kullanabilirsiniz:
const one = valueFromFunctionOne({ some: { complex: inputs } });
const two = valueFromFunctionTwo({ some: { other: inputs } });
expectTypeOf(one).toEqualTypeof<typeof two>();expectTypeOf API'si ile çalışmakta ve hataları anlamakta zorlanıyorsanız, her zaman daha basit assertType API'sini kullanabilirsiniz:
const answer = 42;
assertType<number>(answer);
// @ts-expect-error answer bir string değil
assertType<string>(answer);TIP
@ts-expect-error sözdizimini kullanırken, bir yazım hatası yapmadığınızdan emin olmak isteyebilirsiniz. Bunu, tür dosyalarınızı test.include yapılandırma seçeneğine dahil ederek yapabilirsiniz, böylece Vitest bu testleri gerçekten çalıştırır ve ReferenceError ile başarısız olur.
Bu, bir hata beklediği için geçecektir, ancak "answer" kelimesinde bir yazım hatası olduğu için yanlış pozitif bir hata verecektir:
// @ts-expect-error answer bir string değil
assertType<string>(answr); //Tür Kontrolünü Çalıştırma
Vitest 1.0'dan beri, tür kontrolü için package.json dosyasındaki Vitest komutunuza --typecheck bayrağını eklemeniz yeterlidir:
{
"scripts": {
"test": "vitest --typecheck"
}
}Şimdi tür kontrolünü çalıştırabilirsiniz:
npm run testyarn testpnpm run testbun testVitest, yapılandırmanıza bağlı olarak tsc --noEmit veya vue-tsc --noEmit kullanır, böylece bu komut dosyalarını derleme sürecinizden kaldırabilirsiniz.