15

我正在创建一个处理来自数据库的对象的函数。我有两种不同的数据结构,其中相同的属性具有不同的名称。我无法改变它,所以我必须在 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;为错误(“类型上不存在属性”),因为这两种类型都没有两种属性。

那么,执行此操作的正确打字稿方式是什么?

4

7 回答 7

16

您需要创建一个用户定义的类型保护,然后您可以使用 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;
}

在这里查看。项目正确地转换为 TypeA 或 TypeB。

于 2017-04-19T13:05:08.793 回答
7

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

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 的建议编写类型保护。

于 2017-04-19T13:05:24.953 回答
4

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

if ('itemName' in item) {
    name = item.itemName;
} else {
    name = item.itemTitle;
}
于 2021-03-07T23:59:31.890 回答
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

于 2017-04-19T12:54:38.470 回答
1

我不会把事情复杂化。如果您确实确定您的对象具有一个或另一个属性,则 a name = item['itemName'] || item['itemTitle']orname = item.hasOwnProperty('itemName') ? item['itemName'] : item['itemTitle']就足够了。

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

于 2017-04-19T13:10:13.157 回答
1
interface TypeA {
  a: string
}
interface TypeB {
  b: string
}

const testFunction = (x: TypeA | TypeB): string => {
  return (x as TypeA).a || (x as TypeB).b;
}

testFunction({ a: 'Hello' }); // 'Hello'
testFunction({ b: 'World' }); // 'World'

于 2022-01-16T08:04:04.203 回答
0

使用类型保护

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;
}
于 2017-04-19T13:05:56.643 回答