Birden fazla parametreye sahip bir fonksiyonla Typescript Fonksiyon Aşırı Yüklemesi nasıl kullanılır?
Bir sayılar dizisinde bir değer bulmaya çalışan bir fonksiyonum var. Değer ya bir nesne ya da bir sayı olabilir. Eğer değer bir nesne ise, nesneden sayı değerini almak için kullanılan bir 'key' özelliği vardır.
Tek bir işlevin her iki durumu da işleyebilmesini sağlamak için Fonksiyon Aşırı Yükleme kullanmaya çalışıyorum.
type ObjectType = {
[key: string]: number
}
type FunctionType = {
<T extends ObjectType>(v: T, list: number[], key: string): T | undefined
(v: number, list: number[]): number | undefined
}
const find: FunctionType = <T extends ObjectType | number,>(v: T, list: number[], key?: string)=>{
const value = typeof v === 'number' ? v : v[key]
return list.find((item)=>{
return item === value
})
}
Bu bir hata oluşturur Tanımsız tür bir indeks türü olarak kullanılamaz
Ama bu dalda, v'nin değeri bir nesne, öyleyse key nasıl tanımlı değil?
TS-Oyun Alanı
Teşekkür ederim
Düzenle
Alex Wayne tarafından bir çözüm önerildi, ancak bu değerleri doğru şekilde bir sayıya daraltmıyor.
Eğer list.find'i çağırmak yerine sadece sayı kabul eden özel bir fonksiyon çağırırsak, TypeScript bir hata verecektir
const findNumber = (v: number, list: number[])=>{
/* Do stuff with v as a number */
return list.indexOf(v)
}
const find: FunctionType = <T extends ObjectType | number>(v: T, list: number[], key?: keyof T)=>{
const value = (key && typeof v === 'object') ? v[key] : v
return list[findNumber(value, list)]
}
'ObjectType' türü 'number' türüne atanamaz
TS-Oyun Alanı
Cevap #1
Uygulama fonksiyonu, aşırı yüklemelerinin ne olduğunu bilmez. Bu, bir aşırı yükleme fonksiyonu uygulamasının, aşırı yükleme fonksiyon imzaları kaldırıldığında bile tamamen geçerli olması gerektiği anlamına gelir.
Dolayısıyla, typeof v === 'number' ise typeof key === 'string' olduğu doğru olsa da, derleyici bunu bilmiyor.
Sadece bu fonksiyon imzasına bakarsanız:
<T extends ObjectType | number,>(v: T, list: number[], key?: string)=>{
Sonra find({ someKey: 1 }, [1,2,3])'ün geçerli bir çağrı olduğunu görüyorsunuz. Aşırı yüklemeler bu çağrıyı engelliyor, ama yine de bu fonksiyon bu aşırı yüklemeler olmadan geçerli olmalı.
Bu, bunu düzeltmek için key'i kullanmadan önce varlığını test etmeniz gerekeceği anlamına geliyor.
const value = (key && typeof v === 'number') ? v : v[key]
Ancak bu, yeni bir sorun ortaya çıkarıyor:
Type 'undefined' cannot be used as an index type.(2538)
Bunun nedeni olarak, typeof v === 'number''ın yeterli bir iyileştirme olmaması olduğunu düşünüyorum. Tam olarak başka ne olabileceğini bilmiyorum, ama eğer üçlü operatörü tersine çevirip typeof v === 'object' ile iyileştirirseniz, TypeScript memnun oluyor.
const value = (key && typeof v === 'object') ? v[key] : v
Oyun alanı
Son olarak, burada muhtemelen key: keyof T kullanarak tür güvenliğini artırabilirsiniz.
const find: FunctionType = <T extends ObjectType | number>(v: T, list: number[], key?: keyof T)=>{
const value = (key && typeof v === 'object') ? v[key] : v
return list.find((item)=>{
return item === value
})
}
Oyun alanını gör
Cevap #2
Her şeyden önce, geçersiz durumun temsil edilemez olduğundan emin olalım. Birlik tiplerini tanımlayalım:
type IsObj<T> = {
value: T, key: keyof T
}
type IsNumber = { value: number }
type Params<T> = IsObj<T> | IsNumber
Fark etmiş olabileceğiniz gibi, ikinci ve üçüncü argümanları bağladım.
Şimdi, özel tür koruyucumuzu tanımlayabiliriz:
const isNumber = <T,>(params: Params<T>): params is IsNumber => typeof params.value === 'number'
Hadi hepsini bir araya koyalım:
type ObjectType = {
[key: string]: number
}
type IsObj<T> = {
value: T, key: keyof T
}
type IsNumber = { value: number }
type Params<T> = IsObj<T> | IsNumber
const isNumber = <T,>(params: Params<T>): params is IsNumber => typeof params.value === 'number'
type FunctionType = {
<T extends ObjectType>(list: number[], params: IsObj<T>): T | undefined
(list: number[], params: IsNumber): number | undefined
}
const find: FunctionType = <T extends ObjectType | number,>(list: number[], params: Params<T>) => {
const value = isNumber(params) ? params.value : params.value[params.key]
return list.find((item) => item === value)
}
const result = find([1, 2, 3], { value: 42}) // ok
const result_ = find([1, 2, 3], { value: { age: 2 }, key: 'age' }) // ok
const result__ = find([1, 2, 3], { value: { age: 2 }, key: 'name' }) // expected error
const result___ = find([1, 2, 3], { value: 42, key: 'name' }) // expected error
Oyun alanı
