2017-09-07 1 views
1

Disons que j'ai une union discriminée comme ceci:Way pour segmenter discriminé union en types avec et sans propriété

type Route = HomeRoute | ProfileRoute | BlogRoute; 


type HomeRoute = { 
    route: '/home' 
} 

type ProfileRoute = { 
    route: '/profile/:userId', 
    params: { 
    userId: string; 
    } 
} 

type BlogRoute = { 
    route: '/blog/:teamId', 
    params: { 
    teamId: string; 
    } 
} 

Et j'ai une fonction qui fonctionne sur Route objets, avec une certaine logique en option si elles ont params :

function processRoute(route: Route) { 
    if ('params' in route) { 
    const { params } = route; // <-- this errors 
    } 
} 

Il ne semble pas être un moyen (que je peux voir) pour vérifier params sans ajouter une annotation any ...

function paramsInRoute(route: any): route is { params: {[key: string]: string} } { 
    return ('params' in route); 
} 

function processRoute(route: Route) { 
    if ('params' in route) { 
    const { params } = route; // <-- this errors 
    } 

    if (paramsInRoute(route)) { 
    const { params } = route; // <-- this typechecks 
    } 
} 

Existe-t-il un moyen de faire ce qui précède sans lancer de conversion (dans le paramètre paramsInRoute)?

playground link

Répondre

3

Personnellement, je serais heureux utilisant la garde de type que vous avez:

function paramsInRoute(route: any): route is { params: {[key: string]: string} } { 
    return ('params' in route); 
} 

depuis tapuscrit rétrécissant certainement un objet Route refacturés pour ProfileRoute | BlogRoute

if (paramsInRoute(route)) { 
    const notHomeRouteAnymore: ProfileRoute | BlogRoute = route; // no error 
} 

Mais si vous êtes inquiet au sujet de quelqu'un faire:

const notRoute = "This is not a route"; 
if (paramsInRoute(notRoute)) { notRoute.params.oops = 'what' }; 

alors vous pouvez le faire:

function paramsInRoute(route: Route): route is Route & { params: {[key: string]: string} } { 
    return ('params' in route); 
} 

qui fait la même rétrécissement, mais empêche l'appel erroné:

paramsInRoute(notRoute); // error 

Espérons que cela aide; bonne chance!

+0

si simple! probablement devrait avoir essayé cela d'abord :) –

+0

une pensée supplémentaire à ce sujet, en utilisant les gardes de type est toujours une assertion, donc c'est à la dév pour s'assurer que les propriétés '&' -ed sont corrects ici. –