An example showcasing the use of sum types:
interface Cash {
amount: number,
type: 'cash'
}
interface Card {
amount: number,
type: 'card',
cardNumber: string
}
type Payment = Cash | Card
const displayPayment = (payment: Payment) => {
if (payment.type === 'card') {
console.log(`The payment of ${payment.amount} was made using ${payment.type} with card number ${payment.cardNumber}`)
}
else {
console.log(`The payment of ${payment.amount} was made using ${payment.type}`)
}
}
displayPayment({ type: 'cash', amount: 100 })
displayPayment({ type: 'card', amount: 100, cardNumber: '0123456789' })
Here's another similar example that is no longer functional
interface Cash {
amount: number,
// type now resides within a metadata property
metadata: {
type: 'cash'
}
}
interface Card {
amount: number,
cardNumber: string
// type now resides within a metadata property
metadata: {
type: 'card'
}
}
type Payment = Cash | Card
const displayPayment = (payment: Payment) => {
if (payment.metadata.type === 'card') {
// Error: Property 'cardNumber' does not exist on type 'Payment'. Property 'cardNumber' does not exist on type 'Cash'.
console.log(`Error: Unable to process payment. Amount: ${payment.amount}, Method: ${payment.metadata.type}, Card Number: ${payment.cardNumber}`)
}
else {
console.log(`Unable to process payment. Amount: ${payment.amount}, Method: ${payment.metadata.type}`)
}
}
displayPayment({ metadata: { type: 'cash' }, amount: 100 })
displayPayment({ metadata: { type: 'card' }, amount: 100, cardNumber: '0123456789' })
Why doesn't the sum type functionality work in this case?
It seems like TypeScript struggles to determine the specific type (cash or card) when the defining factor is not located at the outermost layer of the interface (in this scenario, within metadata).