打字稿:映射类型中的枚举键

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了打字稿:映射类型中的枚举键相关的知识,希望对你有一定的参考价值。

我有一个http方法的枚举:

export enum HttpMethod {
  GET = 'GET', POST = 'POST', /*...*/
}

然后我定义一个基本的方法类型,可以有任何HttpMethod作为键:

type Methods = {
  [M in HttpMethod]?: any;
};

基本的Route类型可以使用此Method类型:

type Route<M extends Methods = any> = {
  methods: M;
}

所以我可以定义任何路线,如:

interface AnyRoute extends Route<{
  [HttpMethod.GET]: AnyRequestHandler;
}> {}

到现在为止还挺好。现在我要添加一个Validator

type Validator<R extends Route, M extends HttpMethod> = {/*...*/}

并且只想允许将Methods添加到Validator中定义的Route

type RouteMethodValidators<R extends Route> = {
  [M in keyof R['methods']]?: Validator<R, M>;
};

虽然我的IDE似乎理解它,但我收到以下错误:

  • Type 'M' does not satisfy the constrain 'HttpMethod'.
  • Type 'keyof R["methods"]' is not assignable to type 'HttpMethod'.

有什么方法可以告诉打字稿,这绝对是HttpMethod的成员吗?

答案

你的问题主要在于:type Route<M extends Methods = any>

首先,默认值any将导致Mstring中的RouteMethodValidator类型,因为Route<any>['methods']anykeyof anystring

现在,将默认值更改为Methods仍然无法解决问题,因为你执行M extends Methods这基本上意味着M可以拥有比Methods中定义的更多的键,即比HttpMethods中定义的更多。但在Validator你只允许HttpMethods的值。

我相信你最好的选择是让Route不通用。

type Route = {
  methods: Methods;
}

type RouteMethodValidators<R extends Route> = {
  [M in HttpMethod]?: Validator<R, M>;
}

以上是关于打字稿:映射类型中的枚举键的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:如何根据对象键/值类型在 ES6 映射中创建条目

避免任何类型在打字稿中获取枚举值

打字稿:如何制作接受对象的类型,其键匹配通用但所有值都是值参数的映射函数

打字稿:如何检查一个值是不是是有效的枚举键值? [复制]

如何使用打字稿中的查找来推断类型化的 mapValues?

字符串枚举类似于打字稿中的类型[重复]