Typescript联合类型有误导性

4
以下是代码片段的内容:
interface PalPay {
  email: string;
  someCode: string;
}

interface CreditCard {
  cardNumber: string;
  securityCode: string;
}

const payment: PayPal | CreditCard = {email: 'd@d.d', cardNumber: '1234', securityCode: 'abc'};

我成功创建了一个具有email字段的CreditCard对象。 我应该如何使用TypeScript创建一个既可以是CreditCard又可以是PalPay的对象呢? 这种行为的意义是什么?在什么情况下会有用?


2
https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types - jonrsharpe
它添加了类型,因此您可以看到对象期望的内容,因此它会在编译之前出错,而不像普通JavaScript一样在运行时出错。 - mast3rd3mon
1
请记住:如果我们有一个具有联合类型的值,我们只能访问联合类型中所有类型共有的成员。 - Gab
2
当你期望其中一个对象时,这很有用,但是创建具有类似接口的对象并不真正有用。我的意思是,你不能做 {email: 'd@d.d', cardNumber: '1234', securityCode: 'abc'} 并混合这两个对象。 - Kenry Sanchez
TypeScript没有“exclusive unions”,只要值可以分配给联合类型的任何一个成员,它就是有效的。请参见:https://github.com/Microsoft/TypeScript/issues/10575#issuecomment-242919644 - Aaron Beall
2个回答

2
你在这里误用了联合类型。它不是用来将两个不同的实体合并在一起的,而是作为参数类型在相应的函数中使用的。例如:
interface PayPal {
  email: string;
  someCode: string;
  pay: () => void;
}

interface CreditCard {
  cardNumber: string;
  securityCode: string;
  pay: () => void;
}


handlePayment = (payType: PayPal | CreditCard) => {
   payType.pay();
}

我在接口中添加了pay函数,您可以在Paypal | CreditCard联合类型的handlePayment中调用它。


2
这是一个更典型的用例,但它如何解释为什么 handlePayment({ email: "", cardNumber: "", securityCode: "", pay() { } }) 是被允许的? - Aaron Beall
我们的答案似乎是互补的,这绝对是联合使用的好处。当涉及到联合时,我通常会考虑类型保护,但共同字段也是一个不错的选择 :) - Titian Cernicova-Dragomir

0

联合类型定义了一个可以是联合成员之一的对象,因此在您的示例中,payment 可以是 PayPalCreditCard。当在运行时,payment 可能是任何一个,也许用户可以选择支付方式时,您可以使用这些。联合类型通常与类型保护或辨别联合相关联。请参见此处获取更多信息。

因此,在您的示例中,可能会有一个更现实的示例:

interface PayPal {
    type: "paypal"
    email: string;
    someCode: string;
}

interface CreditCard {
    type: "credit"
    cardNumber: string;
    securityCode: string;
}

declare var userOption: boolean;
let payment: PayPal | CreditCard;
if (userOption) {
    payment = {
        type: "credit",
        cardNumber: '1234', securityCode: 'abc'
    }
} else {
    payment = {
        type: 'paypal',
        email: 'd@d.d', someCode: 'abc'
    }
}
// Later, we can check the type field, 
// and since this field is present on both interfaces 
// and typed to a string literal type 
// the compiler can determine the type of payment 
// in the branches if statement 
if (payment.type === 'credit') {
    console.log(payment.cardNumber); // payment is of type CreditCard
} else {
    console.log(payment.email);// payment is of type PayPal
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接