Aşağıdakine benzer bir yardımcı program türü veren bir kütüphane var:
type Action<Model extends object> = (data: State<Model>) => State<Model>;
Bu yardımcı program türü, "eylem" olarak işlev görecek bir işlevi bildirmenize olanak tanır. Model
Eylemin karşı çıkacağı genel bir argüman alır .
data
"Eylem" argümanı sonra ihracat başka yarar tipiyle yazılan;
type State<Model extends object> = Omit<Model, KeysOfType<Model, Action<any>>>;
Yardımcı State
program türü temel olarak gelen Model
genel kodu alır ve sonra türdeki tüm özelliklerin Action
kaldırıldığı yeni bir tür oluşturur .
Örneğin, yukarıdakilerin temel kullanıcı arazi uygulaması;
interface MyModel {
counter: number;
increment: Action<Model>;
}
const myModel = {
counter: 0,
increment: (data) => {
data.counter; // Exists and typed as `number`
data.increment; // Does not exist, as stripped off by State utility
return data;
}
}
Yukarıdakiler çok iyi çalışıyor. 👍
Bununla birlikte, özellikle genel bir model tanımı tanımlandığında, genel modelin örneklerini üretmek için bir fabrika işleviyle birlikte mücadele ettiğim bir durum var.
Örneğin;
interface MyModel<T> {
value: T; // 👈 a generic property
doSomething: Action<MyModel<T>>;
}
function modelFactory<T>(value: T): MyModel<T> {
return {
value,
doSomething: data => {
data.value; // Does not exist 😭
data.doSomething; // Does not exist 👍
return data;
}
};
}
Yukarıdaki örnekte, data
bağımsız değişkenin doSomething
eylemin kaldırıldığı yere yazılmasını bekliyorum ve genel value
özellik hala var. Ancak durum böyle değildir - value
mülk de tesisimiz tarafından kaldırılmıştır State
.
Bunun nedeni, T
herhangi bir tür kısıtlaması / daralması uygulanmadan genel olması gerektiğine inanıyorum ve bu nedenle tür sistemi, bir türle kesiştiğine karar veriyor Action
ve daha sonra onu data
argüman türünden kaldırıyor .
Bu kısıtlamanın üstesinden gelmenin bir yolu var mı? Biraz araştırma yaptım ve bunun dışındaT
herhangi bir şey olduğunu söyleyebileceğim bir mekanizma olacağını umuyordum . yani negatif tip kısıtlaması.Action
Hayal etmek:
function modelFactory<T extends any except Action<any>>(value: T): UserDefinedModel<T> {
Ancak bu özellik TypeScript için mevcut değildir.
Herkes beklediğim gibi bu işe almak için bir yol biliyor mu?
Burada hata ayıklamaya yardımcı olmak için tam bir kod snippet'i bulunmaktadır:
// Returns the keys of an object that match the given type(s)
type KeysOfType<A extends object, B> = {
[K in keyof A]-?: A[K] extends B ? K : never
}[keyof A];
// Filters out an object, removing any key/values that are of Action<any> type
type State<Model extends object> = Omit<Model, KeysOfType<Model, Action<any>>>;
// My utility function.
type Action<Model extends object> = (data: State<Model>) => State<Model>;
interface MyModel<T> {
value: T; // 👈 a generic property
doSomething: Action<MyModel<T>>;
}
function modelFactory<T>(value: T): MyModel<T> {
return {
value,
doSomething: data => {
data.value; // Does not exist 😭
data.doSomething; // Does not exist 👍
return data;
}
};
}
Bu kod örneğiyle burada oynayabilirsiniz: https://codesandbox.io/s/reverent-star-m4sdb?fontsize=14