在打字稿联合类型中访问不同的属性

KWe*_*iss 2 if-statement object-properties typescript

我正在创建一个函数来处理数据库中的对象。我有两个不同的数据结构,其中相同的属性具有不同的名称。我无法更改它,因此必须使用JavaScript进行处理。
对象具有其他差异,但这对于此功能并不重要。
我想对两种不同类型的对象使用相同的功能。这是演示我的问题的示例代码:

interface TypeA {
    itemName: string;
}

interface TypeB {
    itemTitle: string;
}

function getItemName(item: TypeA | TypeB): string {
    let name = '';

    if (item.hasOwnProperty('itemName')) {
        name = item.itemName;
    } else {
        name = item.itemTitle;
    }

    return name;
}
Run Code Online (Sandbox Code Playgroud)

当然,此代码将运行。但是IDE会将行name = item.itemName;和行都标记name = item.itemTitle;为错误(“类型上不存在属性”),因为两种类型都不具有两种属性。

那么,什么是正确的打字稿方式呢?

the*_*sis 32

我可能有点晚了,但你可以在你的函数中尝试一下:

if ('itemName' in item) {
    name = item.itemName;
} else {
    name = item.itemTitle;
}
Run Code Online (Sandbox Code Playgroud)

  • 这当然是最快的选择!对于一个简单的问题,用户定义的类型防护可能有点矫枉过正。 (2认同)
  • 如果“itemName”类似于“toString”、“valueOf”等,则此操作将会失败。 (2认同)

n00*_*dl3 7

如果您不经常这样做,您可以进行类型断言:

if (item.hasOwnProperty('itemName')) {
    name = (item as TypeA).itemName;
} else {
    name = (item as TypeB).itemTitle;
}
Run Code Online (Sandbox Code Playgroud)

或者

if (item.hasOwnProperty('itemName')) {
    name = (<TypeA>item).itemName;
} else {
    name = (<TypeB>item).itemTitle;
}
Run Code Online (Sandbox Code Playgroud)

如果您需要多次进行此检查,则最好按照@Daryl 的建议编写类型保护。


Dar*_*ryl 5

您需要创建一个用户定义的类型防护,然后可以使用if语句并获取正确的类型。

function isTypeA(value: TypeA | TypeB): value is TypeA {
    return value.hasOwnProperty('itemName');
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使打字更加整洁:

function getItemName(item: TypeA | TypeB): string {
    return isTypeA(item) ? item.itemName : item.itemTitle;
}
Run Code Online (Sandbox Code Playgroud)

检查它在这里。将项目正确转换为TypeA或TypeB。