7 votes

Vérification de type sur Array.map qui retourne des littéraux d'objet

J'ai créé [cet exemple](https://www.typescriptlang.org/play/#src=interface%20Test%7B%0D%0A%20%20%20%20a%3A%20string%0D%0A%20%20%20%20b%3A%20string%0D%0A%7D%0D%0A%0D%0Aconst%20object%3A%20Test%20%3D%20%7B%0D%0A%20%20%20%20a%3A%20'b'%2C%0D%0A%20%20%20%20b%3A%20'c'%2C%0D%0A%7D%0D%0A%0D%0Afunction%20testIt()%3A%20Test%5B%5D%20%7B%0D%0A%20%20%20%20const%20data%20%3D%20%5B%7Bb%3A%20'2'%2C%20c%3A%20'3'%7D%5D%0D%0A%20%20%20%20const%20prices%3A%20Test%5B%5D%20%3D%20data.length%20%3F%20data.map((item)%20%3D%3E%20%7B%0D%0A%20%20%20%20%20%20%20%20return%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20a%3A%20item.b%2C%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20b%3A%20item.c%2C%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20c%3A%20'2'%2C%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20d%3A%20'3'%0D%0A%20%20%20%20%20%20%20%20%7D%0D%0A%20%20%20%20%7D)%20%3A%20%5B%5D%3B%0D%0A%20%20%20%20return%20prices%3B%0D%0A%7D) dans la cour de récréation de TypeScript :

interface Test{
    a: string
    b: string
}

const object: Test = {
    a: 'b',
    b: 'c',
}

function testIt(): Test[] {
    const data = [{b: '2', c: '3'}]
    const prices: Test[] = data.length ? data.map((item) => {
        return {
            a: item.b,
            b: item.c,
            c: '2',
            d: '3'
        }
    }) : [];
    return prices;
}

La suppression de la propriété a ou b de l'instruction de retour de l'objet dans la méthode array map entraîne une erreur TypeScript (comme prévu).

L'ajout de c ou d ou de toute autre propriété inconnue aléatoire ne déclenche pas d'erreur TypeScript. Je soupçonne que cela n'est possible que si l'interface contient [x : string] : any.

Pourquoi Array.map vérifie-t-il les propriétés manquantes d'une interface, mais pas les propriétés supplémentaires ou inconnues ?

6voto

devilmaster Points 439

Le problème est que, selon les règles de base de la POO, un type dérivé (c'est-à-dire un type possédant plusieurs propriétés) doit être compatible avec le type de base (c'est-à-dire le type possédant uniquement des propriétés). a y b ).

Ceci étant dit, Typescript nous avertit lorsque nous assignons des littéraux d'objet avec plus de propriétés alors qu'un type avec moins de propriétés est attendu. C'est ce qu'on appelle le contrôle des propriétés excédentaires. Cette fonctionnalité n'intervient qu'en cas d'affectation DIRECTE à un objet qui n'est pas d'un type donné.

La raison pour laquelle ce contrôle de propriété excédentaire ne s'applique pas dans votre cas est la manière dont le contrôle de type est effectué pour les éléments suivants map . Tout d'abord, le type de retour de la callback est déduit sur la base du littéral de l'objet, il est donc déduit en tant que { a: string, b: string, c: string, d: string } . Ensuite, ce type est utilisé comme type de retour pour la fonction map Así que map retournera un Array<{ a: string, b: string, c: string, d: string }> . Il est ensuite affecté à Test[] ce qui, en vertu de la première règle, est autorisé. Nulle part nous n'avons assigné un objet littéral à un endroit où Test était attendu.

Une façon d'obtenir une erreur est de ne pas laisser typescript déduire le résultat de la callback passée à map . Nous pouvons le faire en ajoutant l'annotation au callback. Nous assignons alors directement un objet littéral à un emplacement qui s'attend à ce que Test :

const prices = data.length ? data.map((item) : Test => {
    return {
        a: item.b,
        b: item.c,
        c: '2', // error
        d: '3'
    }
}) : [];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X