Cum să gestionezi tipurile union de tip duck cu interfețele TypeScript?
Sunt nou în TypeScript și încă încerc să mă obișnuiesc cu lucrurile.
Am un șir de evenimente care formează o cronologie. Ele arată cam așa:
const timeline = [{
type: 'payment',
amount: '12.23 USD',
when: '<iso timestamp>'
},{
type: 'payment',
amount: '12.23 USD',
when: '<iso timestamp>'
},{
type: 'refunded',
amount: '2.00 USD',
when: '<iso timestamp>'
},{
type: 'payment',
amount: '12.23 USD',
when: '<iso timestamp>'
},{
type: 'delinquent',
when: '<iso timestamp>'
}]
Așa că am mers mai departe și am definit un IEvent ca un tip uniune:
interface IPaymentEvent {
amount: string,
when: string
}
interface IRefundedEvent {
amount: string,
when: string
}
interface IDelinquentEvent {
when: string
}
type IEvent = IPaymentEvent | IRefundedEvent | IDelinquentEvent
Problema este că sunt confuz cum să folosesc aceste informații de tip în codul meu. Cum convertesc acea linie temporală în tipurile reale pe care tocmai le-am definit? Și cum deconstruiesc tipul union atunci când iterez peste array?
Încercarea mea arată așa:
class PaymentEvent implements IPaymentEvent {}
class RefundedEvent implements IRefundedEvent {}
class DelinquentEvent implements IDelinquentEvent {}
const duckTypeMap = {
payment: PaymentEvent,
refunded: RefundedEvent,
delinquent: DelinquentEvent
}
const typedTimeline = timeline.map(x => {
return duckTypeMap[x.type](x)
})
console.log(typedTimeline)
Dar asta nu funcționează chiar așa
Am impresia că trebuie să existe o practică comună aici. Sunt, de asemenea, interesat dacă există două moduri de a face acest lucru, (1) cu clase ES6 și (2) fără clase ES6. Pentru acesta din urmă, se pare că sistemul de tipuri ar trebui să poată ajuta dacă îi spunem cum să facă duck type pentru JSON.
Răspuns #1
Ești aproape gata. Câteva lucruri de corectat:
- Pentru a crea o instanță de tip, ar trebui să folosiți cuvântul cheie
new-new duckTypeMap[x.type]; - Pentru a inițializa câmpurile acestei instanțe, ar trebui să creezi un constructor de copiere sau pur și simplu să mapezi obiectul JSON (manual sau cu o bibliotecă). Aruncă o privire la acest răspuns pentru exemplu.
- Dacă clasa ta implementează interfața, ar trebui să declare membrii acestei interfețe. De asemenea, nu sunt sigur ce câștigi folosind tipul
union. Pentru a avea un tablou polimorf, ai putea defini pur și simplu o singură interfațăIEventcu proprietateawhenși să o implementezi în toate clasele.
Ceva de genul acesta:
interface IEvent {
when: string
}
class PaymentEvent implements IEvent {
public amount:string;
public when:string;
}
const typedTimeline:IEvent[] = timeline.map(x => {
let target = new duckTypeMap[x.type];
for (const key in x) {
target[key] = x[key];
}
return target;
});
Pentru a determina tipul unui element atunci când iterați peste array-ul „typed” puteți folosi operatorul instanceof:
if(item instanceof RefundedEvent)
