TypeScript - Genel tipe dayalı koşullu yöntem parametreleri
Yeni bir TypeScript sınıfı yazma sürecindeyim; bu sınıf, bir fonksiyonun girdisi olarak kullanılacak olan genel bir değeri alıyor. Eğer bir değer verilmezse, fonksiyon herhangi bir girdi almamalıdır.
İdeali sınıfın bu şekilde aşırı yüklenmiş olması olurdu.
class Emitter<T = void> {
public activate(): void // When T is void
public activate(arg: T): void // When T isn't void
public activate(arg?: T) { /* ... */ }
}
Yöntemin bir işlev özelliği olması teoride işe yarar ancak yöntemin uygulanmasında bir @ts-ignore gerektirir.
type OneArgFn<T> = T extends void
? () => void
: (arg: T) => void
interface Emitter<T> {
readonly activate: OneArgFn<T>
}
Başka bir olasılık, bir Generic sağlandığında veya sağlanmadığında farklı bir yapıcıyı dışa aktarmaktır, örneğin aşağıdaki gibi
interface EmitterNoArg extends Emitter {
activate: () => true
}
interface EmitterOneArg<T> extends Emitter<T> {
activate: (arg: T) => void
}
interface EmitterConstructor {
new(): Emitter
new(): EmitterNoArg
new<T>(): EmitterOneArg<T>
}
ama sonra bunu dışa aktarmak için unknown anahtar kelimesi gereklidir.
export default Emitter as unknown as EmitterConstructor
Bunlar optimal gibi görünmüyor. Genel tipin türüne dayalı koşullu argümanlara sahip olmanın uygun bir yolu var mı? TypeScript’in yeni koşullu tiplerinin bu sorunu çözeceğini düşünüyorum.
Cevap #1
Bunu yapmanın bir yolu, ayrı bir açık imzada rest parametrelerinde demetler kullanmak olurdu:
type OneArgFn<T> = T extends void
? () => void
: (arg: T) => void
class Emitter<T = void> {
public activate(...a: Parameters<OneArgFn<T>>): void
public activate(arg?: T) { /* ... */ }
}
new Emitter().activate();
new Emitter<string>().activate("") // in 3.4 argument names are preserved
