是否可以根据元组属性中的第一个元素来区分联合类型?
例如
type Landing = {
tokens: ['landing']
};
type Month = {
tokens: ['month', string]
};
type Day = {
tokens: ['day', string, string]
};
type Route =
| Month
| Day
| Landing;
let route: Route = getRoute();
if(route.tokens[0] === 'day') {
// resolve to Day type
}
更新: 如果没有直接的方法来做到这一点,我会很高兴使用自定义类型防护,但还无法让其工作。为了澄清,我想要一个可以区分联合的类型保护器,而不是对每个变体进行显式检查。
例如
if(typeGuard(route, 'day')) {
// compiler knows this id Day type
}
else if(typeGuard(route, 'month')) {
// compiler knows this is Month type
}
最佳答案
编辑 自最初的答案以来, typescript 在区分联合方面已经变得更好,因此这在 typescript 3.3 中按预期工作:
if (route.tokens[0] === "day") {
// resolve to Day type
route.tokens[0] === 'day'
} else if (route.tokens[0] === "landing") {
// resolve to Landing type
route.tokens[0] === 'landing'
} else {
// resolve to Month type
route.tokens[0] === 'month'
}
原创
虽然为每个联合成员编写类型保护的解决方案是完全有效的,但如果联合中有许多成员或者稍后向联合添加额外的成员,它确实会产生问题。
您可以使用 Extract
条件类型创建一个自定义类型保护来保护所有可能的类型:
type Landing = {
tokens: ['landing']
};
type Month = {
tokens: ['month', string]
};
type Day = {
tokens: ['day', string, string]
};
type Route =
| Month
| Day
| Landing;
declare let route: Route;
function isRoute<T extends Route['tokens'][0]>(r: Route, type: T): r is Extract<Route, { tokens: [T, ...any[]] }> {
return route.tokens[0] === type;
}
if (isRoute(route, 'day')) {
// resolve to Day type
route.tokens[0] === 'day'
} else if (isRoute(route, 'landing')) {
// resolve to Landing type
route.tokens[0] === 'landing'
} else {
// resolve to Month type
route.tokens[0] === 'month'
}
关于TypeScript:区分元组中的联合和值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53073066/