Je crée un widget dynamique, qui peut être vide ou rempli. Il doit être vide par défaut. Lorsque populated={true}, je souhaite que les valeurs totalGross et totalNet soient obligatoires. Sinon, ces 2 accessoires ne devraient pas être autorisés.

Pour cela, j'essaye d'utiliser un type discriminant (WidgetBodyProps). Cependant, TypeScript se plaint parce que totalNet et totalGross sont des accessoires obligatoires dans <WidgetBodyPopulated />

type WidgetBodyProps =
    | { isEmpty?: false; totalNet: string; totalGross: string }
    | { isEmpty: true; totalNet?: never; totalGross?: never };

type WidgetProps = WidgetHeaderProps & WidgetBodyProps;

const Widget = (props: WidgetProps) => {
    const { title = "", isEmpty = true, totalNet, totalGross } = props;

    return (
        <Card>
            <Box>
                <WidgetHeader title={title} />
                <Divider my="4" />
                {isEmpty ? (
                    <WidgetBodyEmpty flex="1" />
                ) : (
                    <WidgetBodyPopulated totalNet={totalNet} totalGross={totalGross} />
                )}
            </Box>
        </Card>
    );
};

Comment puis-je corriger cette erreur Typescript? Erreur TS

2
Bassem 15 janv. 2021 à 03:03

2 réponses

Meilleure réponse

Une fois que vous avez déstructuré les accessoires, Typescript oublie qu'ils n'étaient jamais liés. Ainsi, un test sur une variable ne discriminera pas le type d'une autre. Mais au moment où vous déstructurez props vous n'avez pas testé son type, donc toutes les variables sont typées avec toutes les possibilités.

Cependant, si vous évitez la déstructuration, alors Typescript peut garder un œil sur le type de props. De cette façon, tester une prépropriété d'accessoires réduit le type d'accessoires que vous attendez.

{props.isEmpty ? (
    <WidgetBodyEmpty flex="1" />
) : (
    <WidgetBodyPopulated
      totalNet={props.totalNet}
      totalGross={props.totalGross}
    />
)}

Ensuite, vous pouvez même simplifier ces accessoires pour:

type WidgetBodyProps =
    | { isEmpty?: false; totalNet: string; totalGross: string }
    | { isEmpty: true };

Parce que vous n'accédez jamais à .totalNet sans vérifier .isEmpty au préalable.

Exemple de travail

1
Alex Wayne 15 janv. 2021 à 00:33

Habituellement, cette erreur se produit car Typescript ne vous croit pas que quelque chose n'est pas nul. Utilisez un non- opérateur d'assertion null pour indiquer à Typescript qu'il peut être sûr que vous savez ce que vous faites et que vous ne lui donnerez pas la valeur null. L'autre option serait de s'assurer que les variables en question sont correctement définies pour être des chaînes vides.

0
Forrest 15 janv. 2021 à 00:16
65728659