Tür Testleri
Örnek Proje
Vitest, expectTypeOf
veya assertType
sözdizimlerini kullanarak türleriniz için testler yazmanıza olanak tanır. Varsayılan olarak *.test-d.ts
uzantılı tüm dosyalar tür testi olarak kabul edilir, ancak bu davranışı typecheck.include
yapılandırma seçeneğiyle değiştirebilirsiniz.
Vitest, yapılandırmanıza bağlı olarak arka planda tsc
veya vue-tsc
komutlarını çağırır ve sonuçları ayrıştırır. Kaynak kodunuzda tür hataları bulunursa, Vitest bunları da raporlayacaktır. Bu özelliği typecheck.ignoreSourceErrors
yapılandırma seçeneğiyle devre dışı bırakabilirsiniz.
Vitest'in bu dosyaları çalıştırmadığını, yalnızca derleyici tarafından statik olarak analiz edildiğini unutmamak önemlidir. Bu, dinamik bir ad veya test.each
veya test.for
kullanırsanız, test adının değerlendirilmeyeceği ve olduğu gibi görüneceği anlamına gelir.
WARNING
Vitest 2.1'den önce, typecheck.include
ayarınız include
kalıbını geçersiz kılıyordu, bu nedenle çalışma zamanı testleriniz aslında çalışmıyordu; yalnızca tür kontrolü yapılıyordu.
Vitest 2.1'den beri, include
ve typecheck.include
ayarlarınız çakışıyorsa, Vitest tür testlerini ve çalışma zamanı testlerini ayrı öğeler olarak raporlayacaktır.
--allowOnly
ve -t
gibi CLI bayraklarının kullanımı da tür kontrolü için desteklenir.
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 string bekleniyor
assertType(mount({ name: 42 }));
});
Bir test dosyasında tetiklenen herhangi bir tür hatası bir test hatası olarak ele alınacaktır, böylece projenizin türlerini test etmek için istediğiniz herhangi bir tür tekniğini kullanabilirsiniz.
Olası eşleşenlerin bir listesini API bölümünde görebilirsiniz.
Hataları Okuma
expectTypeOf
API'sini kullanıyorsanız, expect-type belgelerindeki hata mesajlarına bakın.
Türler eşleşmediğinde, .toEqualTypeOf
ve .toMatchTypeOf
, hata mesajlarını mümkün olduğunca anlaşılır hale getirmek için özel bir yardımcı tür kullanır. Ancak bunları anlamanın belli bir nüansı vardır. Doğrulamalar "zincirleme" bir şekilde yazıldığından, hata "beklenen" türde olmalı, "gerçek" türde değil (expect<Actual>().toEqualTypeOf<Expected>()
). Bu, tür hatalarının biraz kafa karıştırıcı olabileceği anlamına gelir - bu nedenle bu kütüphane, beklentinin ne olduğunu netleştirmek için bir MismatchInfo
türü üretir. Örneğin:
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();
Bu test, {a: 1}
değerinin {a: number}
türünde olduğu ve {a: string}
olmadığı için başarısız olacaktır. Bu durumda hata mesajı şöyle görünecektir:
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}>()
Bildirilen tür kısıtlamasının hem "beklenen" hem de "gerçek" türleri belirten anlaşılır bir mesaj olduğunu akılda tutun. Types of property 'a' are incompatible // Type 'string' is not assignable to type "Expected: string, Actual: number"
cümlesini harfiyen yorumlamak yerine, sadece özellik adına ('a'
) ve mesaja bakın: Expected: string, Actual: number
. Bu, çoğu durumda neyin yanlış olduğunu size gösterecektir. Son derece karmaşık türlerin hata ayıklaması elbette daha fazla çaba gerektirecek ve biraz deneme yanılma gerektirebilir. Hata mesajları gerçekten yanıltıcıysa lütfen bir sorun kaydı oluşturun.
toBe...
yöntemleri (toBeString
, toBeNumber
, toBeVoid
vb. gibi), test edilen Actual
türü eşleşmediğinde çağrılamaz bir türe dönüşerek başarısız olur. Örneğin, expectTypeOf(1).toBeString()
gibi bir doğrulama için hata şöyle görünecektir:
test/test.ts:999:999 - error TS2349: This expression is not callable.
Type 'ExpectString<number>' has no call signatures.
999 expectTypeOf(1).toBeString()
~~~~~~~~~~
This expression is not callable
kısmı pek yardımcı değil - anlamlı hata bir sonraki satırda: Type 'ExpectString<number>' has no call signatures
. Bu esasen bir sayı ilettiğiniz ancak bir string olması gerektiğini belirttiğiniz anlamına gelir.
TypeScript "throw" türleri desteği ekleseydi bu hata mesajları önemli ölçüde geliştirilebilirdi. O zamana kadar belirli bir miktar dikkatli inceleme gerektirecekler.
Somut "beklenen" nesneler ile tür argümanları
Şunun gibi bir doğrulama için hata mesajları:
expectTypeOf({ a: 1 }).toEqualTypeOf({ a: '' });
Şunun gibi bir doğrulama için olduğundan daha az yardımcı olacaktır:
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();
Bunun nedeni, TypeScript derleyicisinin .toEqualTypeOf({a: ''})
için tür argümanını çıkarması gerekmesidir ve bu kütüphane bunu yalnızca genel bir Mismatch
türüyle karşılaştırarak bir hata olarak belirleyebilir. Bu nedenle, mümkün olduğunda, .toEqualTypeOf
ve toMatchTypeOf
için somut bir tür kullanmak yerine bir tür argümanı kullanılması önerilir. İki somut türü karşılaştırmak daha uygunsa, 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 olmanız önerilir. Bunu, tür dosyalarınızı test.include
yapılandırma seçeneğine dahil ederek sağlayabilirsiniz, böylece Vitest bu testleri gerçekten çalıştıracak ve ReferenceError
ile başarısız olacaktır.
Bu test başarılı olacaktır, çünkü bir hata beklenmektedir, ancak "answer" yerine "answr" yazılarak yapılan yazım hatası nedeniyle bu yanlış pozitif bir hatadır:
// @ts-expect-error answer bir string değil
assertType<string>(answr);
Tür Kontrolünü Çalıştırmak
Tür kontrolünü etkinleştirmek için, package.json
dosyanızdaki Vitest komutunuza --typecheck
bayrağını eklemeniz yeterli olacaktır:
{
"scripts": {
"test": "vitest --typecheck"
}
}
Şimdi tür kontrolünü çalıştırabilirsiniz:
npm run test
yarn test
pnpm run test
bun test
Vitest, 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.