属性 ‘x’ 在类型上不存在(在检查其是否存在时)

huangapple go评论89阅读模式
英文:

Property 'x' does not exist on type (when checking if it exists)

问题

我当前代码的相关部分如下所示:
(代码编辑自 https://github.com/expo/expo-server-sdk-node

  const tickets: ExpoPushTicket[] = [], receiptIds = [];

  ...

  for (const ticket of tickets) {
    if (ticket.id) {
      receiptIds.push(ticket.id);
    }
  }

类型定义如下(来自 expo-server-sdk 库):

export declare type ExpoPushSuccessTicket = {
    status: 'ok';
    id: ExpoPushReceiptId;
};
export declare type ExpoPushErrorTicket = ExpoPushErrorReceipt;
export declare type ExpoPushErrorReceipt = {
    status: 'error';
    message: string;
    details?: {
        error?: 'DeviceNotRegistered' | 'InvalidCredentials' | 'MessageTooBig' | 'MessageRateExceeded';
    };
    __debug?: any;
};
export declare type ExpoPushTicket = ExpoPushSuccessTicket | ExpoPushErrorTicket;

问题是 if (ticket.id) 报错 Property 'id' does not exist on type 'ExpoPushTicket'
if 语句的目的是检查属性 id 是否存在,因为只有在出现错误时它才是未定义的。
我尝试使用 Object.prototype.hasOwnProperty 方法来避免在 if 行上出现编译错误,但在 receiptIds.push(ticket.id) 上仍然存在错误。
请问,如何正确地检查我的 ticket 是否包含该属性?
我应该导入并更改 ExpoPushTicket 的类型吗?

英文:

The relevant part of my current code looks like this:
(code edited from https://github.com/expo/expo-server-sdk-node)

  const tickets: ExpoPushTicket[] = [], receiptIds = [];

  ...

  for (const ticket of tickets) {
    if (ticket.id) {
      receiptIds.push(ticket.id);
    }
  }

where the types look like this (from expo-server-sdk library):

export declare type ExpoPushSuccessTicket = {
    status: 'ok';
    id: ExpoPushReceiptId;
};
export declare type ExpoPushErrorTicket = ExpoPushErrorReceipt;
export declare type ExpoPushErrorReceipt = {
    status: 'error';
    message: string;
    details?: {
        error?: 'DeviceNotRegistered' | 'InvalidCredentials' | 'MessageTooBig' | 'MessageRateExceeded';
    };
    __debug?: any;
};
export declare type ExpoPushTicket = ExpoPushSuccessTicket | ExpoPushErrorTicket;

The issue is if (ticket.id) gives Property 'id' does not exist on type 'ExpoPushTicket'.
The purpose of the if in itself was to see if the property id existed, since it's undefined only if there is an error.
I checked to see if there were other methods and found Object.prototype.hasOwnProperty which managed to not give a compilation error on the if line, but the error was still there on receiptIds.push(ticket.id).
What is the correct way to check if my ticket contains the property?
Should I import and change the type of ExpoPushTicket?

答案1

得分: 1

类型ExpoPushTicket是一个联合类型。如果没有类型保护,只有在所有联合成员上存在该属性时才能访问它。在你的情况下,首先使用类型保护检查特定类型,然后访问id字段。

最简单的解决方案可能是使用in运算符:

for (const ticket of tickets) {
  if ("id" in ticket) {
    receiptIds.push(ticket.id);
  }
}

这个检查将联合类型缩小到ExpoPushSuccessTicket,在这个类型上访问id字段是合法的。

英文:

The type ExpoPushTicket is a union type. Without a type guard you can only access a property if it exists on all union participants. In your case check first for a specific type using a type guard and then access the id field.

The simplest solution is probably the in operator:

  for (const ticket of tickets) {
    if ("id" in ticket) {
      receiptIds.push(ticket.id);
    }
  }

This check narrows the union type to ExpoPushSuccessTicket where accessing the id field is legal.

huangapple
  • 本文由 发表于 2023年7月27日 16:58:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76778113.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定