TypeScript - sadece arayüz üyeleri çıkarılabilir mi - mümkün mü?
Bir arayaza ait bir objeden üyeleri dinamik olarak (yani tekrar açıkça belirtmeden) çıkarmanın bir yolu var mı, şöyle ki:
let subset = { ...someObject as ISpecific };
Şu anda bazı nesnelerin sahip olduğu tüm üyeleri alıyorum. Yani burada spread operatörü işe yaramıyor. Bunu yapmanın henüz bir yolu var mı?
Örnek :
interface ISpecific { A: string; B: string; }
class Extended implements ISpecific { public A: string = '1'; public B: string = '2'; public C: string = '3'; }
let someObject = new Extended();
let subset = { ...someObject as ISpecific };
console.log(subset); // -> { A, B, C } but want { A, B }
TypeScript tipleri yalnızca derleyici için ipuçlarıdır, çalışma zamanında gerçek dönüşümler değildir.
Cevap #1
Typescript arayüzleri çalışma zamanında mevcut olmadığı için, onları herhangi bir çalışma zamanı davranışını yönlendirmek için kullanamayız, sadece derleme zamanı tür kontrolü yapabiliriz. Ancak, arayüzle aynı özelliklere sahip bir nesne oluşturabiliriz (örneğin başlatmayı basitleştirmek için tüm özellikleri true türünde olacak şekilde) ve eğer bu nesne arayüzden fazla veya eksik alana sahipse derleyicinin hata vermesini sağlayabiliriz. Bu nesneyi hangi özellikleri çıkaracağımız konusunda rehber olarak kullanabiliriz:
function extract<T>(properties: Record<keyof T, true>){
return function<TActual extends T>(value: TActual){
let result = {} as T;
for (const property of Object.keys(properties) as Array<keyof T>) {
result[property] = value[property];
}
return result;
}
}
interface ISpecific { A: string; B: string; }
const extractISpecific = extract<ISpecific>({
// This object literal is guaranteed by the compiler to have no more and no less properties then ISpecific
A: true,
B: true
})
class Extended implements ISpecific { public A: string = '1'; public B: string = '2'; public C: string = '3'; }
let someObject = new Extended();
let subset = extractISpecific(someObject);
Cevap #2
Kullandığınız türleri sınırlamak istiyorsanız, bunu basit ve güvenli bir şekilde şununla yapabilirsiniz:
let subset = someObject as ISpecific;
Özellikler yine de subset üzerinde mevcut olacak, ancak derleyici bunlara bağlı kalmanızı engelleyecek, yani aşağıda subset.age başarısız olacak, ancak özellik yine de mevcut.
interface ISpecific {
name: string;
}
const someObject = {
name: 'Fenton',
age: 21
};
let subset = someObject as ISpecific;
console.log(subset.age);
Özellikleri gerçekten böyle dağıtarak atabilirsiniz, tehlike şurada ki, ...subset'ten önce listede "istemediğim tüm şeyleri" dahil etmeniz gerekir.
interface ISpecific {
name: string;
}
const someObject = {
name: 'Fenton',
age: 21
};
let { age, ...subset } = someObject;
console.log(JSON.stringify(someObject));
console.log(JSON.stringify(subset));
