繁体   English   中英

将有区别的联盟划分为有和没有财产的类型的方法

[英]Way to segment discriminated union into types with and without property

让我们说我有一个像这样的歧视联盟:

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

我有一个在Route对象上运行的函数,如果它们有params,则有一些可选的逻辑:

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

似乎没有办法(我可以看到)检查params而不添加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
  }
}

有没有办法在没有强制转换的情况下(在paramsInRoute的参数中)执行上述操作?

游乐场链接

我个人非常乐意使用您拥有的型号后卫:

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

因为TypeScript肯定会将传入的Route对象缩小为ProfileRoute | BlogRoute

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

但如果你担心有人这样做:

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

然后你可以这样做:

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

它做同样的缩小但防止错误的电话:

paramsInRoute(notRoute); // error

希望有所帮助; 祝好运!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM