【发布时间】:2020-08-24 04:31:06
【问题描述】:
说,我有一个类似的结构
//Modified from https://blog.parametricstudios.com/posts/pattern-matching-custom-data-types/.
enum RouteEnum
{
Home = "/",
Todos = "/todos",
Todo = "/todos/:id",
NotFound = "*"
}
class HomeLocation
{
readonly route = RouteEnum.Home;
match<Out>(matcher: LocationMatcher<Out>): Out
{
return matcher[RouteEnum.Home](this);
}
}
// A list of all Todo item links, when one is linked the next route is in TodoLocation.
class TodosLocation
{
readonly route = RouteEnum.Todos;
match<Out>(matcher: LocationMatcher<Out>): Out
{
return matcher[RouteEnum.Todos](this);
}
}
// A single Todo location.
class TodoLocation
{
readonly route = RouteEnum.Todo;
match<Out>(matcher: LocationMatcher<Out>): Out
{
return matcher[RouteEnum.Todo](this);
}
}
class NotFoundLocation
{
readonly route = RouteEnum.NotFound;
match<Out>(matcher: LocationMatcher<Out>): Out
{
return matcher[RouteEnum.NotFound](this);
}
}
type NewLocation = HomeLocation | TodosLocation | TodoLocation | NotFoundLocation;
type LocationMatcher<Out> =
{
[RouteEnum.Home]: (route: HomeLocation) => Out;
[RouteEnum.Todos]: (route: TodosLocation) => Out;
[RouteEnum.Todo]: (route: TodoLocation) => Out;
[RouteEnum.NotFound]: (route: NotFoundLocation) => Out;
};
是否可以将NewLocation 变成类似的结构
// The matching order here is from the the first to latter.
const routes = {
'/': HomeLocation,
'/todos': TodosLocation,
'/todos/:id': TodoLocation,
'/*': NotFoundLocation
}
如果它很重要,这个问题的更大原因是我正在考虑在这个结构上进行路由匹配,但自然需要一种方法将 URL 转换为那些 *Location 类。
一个例子可能是使用https://github.com/CaptainCodeman/js-router 之类的东西(或者更适合这种结构的类似方法)。例如,这个特定的库在类似routes 示例的结构上运行。我认为,即使不使用这个特定的库,知道如何枚举有区别的联合并创建一个新类型也是很好的了解信息。
目标是将解析的参数作为强类型。当然,这是手动的,但他们需要首先从*Location 类中的相应路由以一种或另一种方式进行匹配。一种选择是为每个 *Location 类设置一个回调函数,该函数从匹配的路由中获取输入。
编辑 我写了一个 StackBlitz 来更好地说明我的思考。在https://stackblitz.com/edit/typescript-hl6drb?file=index.ts。
【问题讨论】:
-
'/article/*和Todo是错别字吗?他们应该分别是'*'和TodoLocation吗? -
啊,是的。我在写这篇文章时从引用的
js-router复制了最后一部分,并思考如何在我的 n00b TS 知识中弥合这种“枚举歧视联合”的差距。我编辑文本,只需几秒钟。 -
问题标题也让我感到困惑。我没有看到问题正文中任何地方提到的元组数组。或者任何数组或任何元组,就此而言。
-
这一定是我的n00b TS技能。我的意思是
const routes = {部分,现在我想到它是一个对象。我还认为,与您的快速回答有关,我的问题是将NewLocation转换为像const routes = {这样的运行时结构,这样我就可以轻松使用js-router库,而无需多次编写字符串,或者可能使用该库代码并对其进行重构以直接处理该结构。 -
所以“运行时结构”是指您希望将 type
NewLocation转换为发出 JavaScript 的东西?答案是“你不能那样做”;这违反了 TS 设计目标(具体来说,它是non-goal #5)。 TS 的类型系统旨在描述,而不是发出 JS。你可以做相反的事情;编写你的运行时结构,然后为它生成一个类型。
标签: typescript