打字稿联合类型具有误导性[关闭]

Posted

技术标签:

【中文标题】打字稿联合类型具有误导性[关闭]【英文标题】:Typescript union types is misleading [closed] 【发布时间】:2018-07-04 22:04:29 【问题描述】:

按照代码 sn-p :

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 对象。 我应该如何使用打字稿来创建 CreditCard 或 PalPay 的对象? 无论如何,这种行为有什么意义?这在什么情况下有用?

【问题讨论】:

typescriptlang.org/docs/handbook/… 它添加了类型,因此您可以看到对象期望的内容,因此它会在编译前出错,而不是像 vanilla javascript 那样在运行时出错 记住:If we have a value that has a union type, we can only access members that are common to all types in the union. 当您期望其中一个对象时它很有用,但对于创建具有类似接口的对象并不是很有用。我的意思是,你不能在 email: 'd@d.d', cardNumber: '1234', securityCode: 'abc' 中混合使用这两个对象。 TypeScript 没有“独占联合”,只要该值可分配给联合的成员之一,它就有效。见:github.com/Microsoft/TypeScript/issues/… 【参考方案1】:

联合类型定义的对象可以是联合的任何一个组成部分,因此在您的示例中,payment 可以是 PayPalCreditCard。您可以在运行时使用这些,payment 可能是,也可能是用户可以选择付款方式。联合类型通常与类型保护或区分联合相关联。在这里查看more

所以在你的例子中,一个更现实的例子可能是:

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

【讨论】:

【参考方案2】:

您在那里滥用联合类型。它并不意味着将两个不同的实体组合在一起并将其合并在一起。它旨在用作可以在相应函数中处理的参数类型,例如

interface PayPal 
  email: string;
  someCode: string;
  pay: () => void;


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



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

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

【讨论】:

这是一个更典型的用例,但它如何解释为什么 handlePayment( email: "", cardNumber: "", securityCode: "", pay() ) 会被允许? 我们的答案似乎是互补的,这绝对是对工会的一种很好的利用。我通常认为在涉及工会时键入 guars,但公共字段也是一个很好的用途:)

以上是关于打字稿联合类型具有误导性[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

差异联合类型和区分联合打字稿/ F#

在打字稿中创建数组类型[关闭]

打字稿不正确的分配/映射到强类型对象[关闭]

打字稿:将标记的联合转换为联合类型

打字稿:检查类型是不是为联合

将打字稿接口属性类型转换为联合[重复]