typescript - DRY olmak için bir tipin içinde "geçici" bir tip nasıl oluşturabilirim?
Bu soruyu SO'da nasıl arayacağımı bile bilmiyorum. Benim genel tipim FetchOptions aslında şudur:
type FetchOptions<T> = {
explode?: string & keyof T | (string & keyof T)[];
}
Sonraki dizi tanımındaki tekrarları önlemek için başka bir tür string & keyof T oluşturmanın bir yolunu bulamıyorum ve bunu türü çıkarmadan yapmak istiyorum (türün içinde):
type Key<T> = string & keyof T;
type Options<T> = {
explode?: Key<T> | Key<T>[];
}
Örnek kullanım:
class Product {
id: number | string;
name: string;
variants?: ProductVariant[];
attributes?: ProductVariant[];
}
const fetchProducts = (options: FetchOptions<Product> = {}) => {
// ...
};
fetchProducts({ explode: 'variants' });
fetchProducts({ explode: ['variants', 'attributes'] });
Cevap #1
Tekrarı önlemek için sıklıkla varsayılan değerlere sahip ek genel parametreler kullanıldığını görüyorum.
type FetchOptions<T, E = string & keyof T> = {
explode?: E | E[];
}
FetchOptions<Product> gibi kullanıldığında, öncekine benzer bir davranış elde edersiniz. Ancak yanlışlıkla ikinci bir generic parametre sağlamaktan endişelenmeniz gerekebilir. E bir kısıtlama değildir, bu nedenle herhangi bir tür FetchOptions için geçebilir.
Doğru türü garanti edecek bir kısıtlama ekleyebiliriz.
type FetchOptions<T, E extends string & keyof T = string & keyof T> = {
explode?: E | E[];
}
Ama bu, türü iki kez yazmamızı gerektirdiği için, muhtemelen tür daha sık kullanılıyorsa faydalıdır.
Oyun alanı
Cevap #2
infer ile bir 'kapsamlı tür' gibi bir şey elde etmek mümkündür.
Ana genel türde ek parametreler gerekmez.
Ayrıca yalnızca tür parametrelerine dayanmadığı için, yeni türetilmiş herhangi bir türü kullanabileceğinden, karmaşık bir ifadede daha fazla esnekliğe de sahiptir.
type FetchOptions<T> =
(string & keyof T) extends (infer E) ?
// scope starts
{ explode?: E | E[]; } :
// scope ends
never;
