访问打字稿联合类型中的不同属性
Accessing different properties in a typescript union type
我正在创建一个函数来处理数据库中的对象。我有两个不同的数据结构,其中相同的 属性 具有不同的名称。我无法更改它,所以我必须在 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;
都标记为错误 ("Property does not exist on type"),因为这两种类型不具有两个属性。
那么,正确的打字稿方式是什么?
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
您需要创建一个用户定义的类型保护,然后您可以使用 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。
如果您不经常这样做,您可以进行类型断言:
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 的建议编写一个类型保护。
使用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;
}
我不会把事情复杂化。如果您真的确定您的对象具有一个或另一个 属性,那么 name = item['itemName'] || item['itemTitle']
或 name = item.hasOwnProperty('itemName') ? item['itemName'] : item['itemTitle']
就足够了。
请注意,如果您使用括号表示法而不是点表示法访问属性,TypeScript 通常会停止报错。不过,我建议添加评论。
我可能来晚了一点,但你可以在你的函数中试一试:
if ('itemName' in item) {
name = item.itemName;
} else {
name = item.itemTitle;
}
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'
我正在创建一个函数来处理数据库中的对象。我有两个不同的数据结构,其中相同的 属性 具有不同的名称。我无法更改它,所以我必须在 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;
都标记为错误 ("Property does not exist on type"),因为这两种类型不具有两个属性。
那么,正确的打字稿方式是什么?
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
您需要创建一个用户定义的类型保护,然后您可以使用 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。
如果您不经常这样做,您可以进行类型断言:
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 的建议编写一个类型保护。
使用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;
}
我不会把事情复杂化。如果您真的确定您的对象具有一个或另一个 属性,那么 name = item['itemName'] || item['itemTitle']
或 name = item.hasOwnProperty('itemName') ? item['itemName'] : item['itemTitle']
就足够了。
请注意,如果您使用括号表示法而不是点表示法访问属性,TypeScript 通常会停止报错。不过,我建议添加评论。
我可能来晚了一点,但你可以在你的函数中试一试:
if ('itemName' in item) {
name = item.itemName;
} else {
name = item.itemTitle;
}
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'