2017-04-19 5 views
0

Je crée une fonction qui gère les objets de la base de données. J'ai deux structures de données différentes où la même propriété a un nom différent. Je ne peux pas changer cela, donc je dois le gérer en JavaScript.
Les objets ont d'autres différences, mais ce n'est pas important pour cette fonction.
Je souhaite utiliser la même fonction pour deux types d'objets différents. Voici un exemple de code démontrant mon problème:Accès à différentes propriétés dans un type d'union de typescript

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; 
} 

Bien sûr, ce code s'exécute. Mais l'IDE marque à la fois les lignes name = item.itemName; et name = item.itemTitle; comme des erreurs ("La propriété n'existe pas sur le type"), car les deux types n'ont pas les deux propriétés. Alors, quelle est la bonne façon de faire cela?

Répondre

2

Vous devez créer un utilisateur type défini par la Garde, vous pouvez utiliser une instruction if et obtenez la bonne frappe.

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

Ensuite, vous pouvez obtenir le frappe beaucoup plus propre:

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

Check it out here. L'élément est correctement transtypé en TypeA ou TypeB.

1

Intellij accepte cette syntaxe:

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

la voie officielle selon les dactylographiées docs est ceci: https://www.typescriptlang.org/docs/handbook/functions.html

1

vous pouvez faire une affirmation de type si vous ne le faites pas trop souvent:

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

ou

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

si vous avez besoin de faire cette vérification, plus d'une fois ou deux fois, vous d mieux écrire un garde de type comme @Daryl suggère.

0

Utilisation 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; 
} 
0

Je ne vais pas compliquer les choses. Si vous êtes vraiment certain que votre objet possède l'une ou l'autre propriété, un name = item['itemName'] || item['itemTitle'] ou name = item.hasOwnProperty('itemName') ? item['itemName'] : item['itemTitle'] suffirait.

Notez que TypeScript arrête généralement de se plaindre si vous accédez aux propriétés en utilisant la notation de parenthèse au lieu de la notation par points. Je suggère d'ajouter un commentaire, cependant.