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

时间:2017-04-19 12:45:31

标签: if-statement typescript object-properties

我正在创建一个处理数据库中对象的函数。我有两个不同的数据结构,其中相同的属性具有不同的名称。我不能改变它,所以我必须用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;
}

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

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

6 个答案:

答案 0 :(得分:4)

您需要创建一个User Defined Type Guard,然后您可以使用if语句并获得正确的输入。

function isTypeA(value: TypeA | TypeB): value is TypeA {
    return value.hasOwnProperty('itemName');
}

然后你可以让打字更清洁:

function getItemName(item: TypeA | TypeB): string {
    return isTypeA(item) ? item.itemName : item.itemTitle;
}

查看here。项目正确地转换为TypeA或TypeB。

答案 1 :(得分:1)

Intellij接受这种语法:

function getItemName(item: TypeA): string;
function getItemName(item: TypeB): string;
function getItemName(item): string {
    return item.hasOwnProperty('itemName') ? item.itemName : item.itemTitle;
}

根据打字稿文件的官方方式是这样的: https://www.typescriptlang.org/docs/handbook/functions.html

答案 2 :(得分:1)

如果你不经常这样做,你可以做出类型断言:

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

if (item.hasOwnProperty('itemName')) {
    name = (<TypeA>item).itemName;
} else {
    name = (<TypeB>item).itemTitle;
}

如果你需要进行一次或两次以上的检查,你最好像@Daryl建议的那样写一个打字卫士。

答案 3 :(得分:1)

我可能会迟到,但你可以在你的函数中试试这个:

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

答案 4 :(得分:0)

使用typeguards

interface TypeA {
    itemName: string;
}

interface TypeB {
    itemTitle: string;
}

function isTypeA(val: any): val is TypeA
{
    return val.hasOwnProperty('itemName');
}

function isTypeB(val: any): val is TypeB
{
    return val.hasOwnProperty('itemTitle');
}

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

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

    return name;
}

答案 5 :(得分:0)

我不会让事情变得复杂。如果您确定您的对象具有该属性,则name = item['itemName'] || item['itemTitle']name = item.hasOwnProperty('itemName') ? item['itemName'] : item['itemTitle']就足够了。

请注意,如果使用括号表示法而不是点表示法访问属性,则TypeScript通常会停止抱怨。不过,我建议添加评论。