【问题标题】:Typescript - typesafe mapping of a key to both types and valueTypescript - 键到类型和值的类型安全映射
【发布时间】:2021-06-01 21:10:43
【问题描述】:

我的目标是拥有一个函数,该函数接受一个键和一个带有查询参数的对象,并且该函数可以查找一个 URL,插入查询参数并导航到该 URL。到目前为止我得到的是这个

  interface FooIdParams {
    fooId: number;
  }

  interface QueryParams<P = never> {
    params: P;
  }

  enum Urls {
    'foo-editor' = '/editfoo?fooId=${fooId}'
  }

  interface ParamTypes {
    'foo-editor': QueryParams<FooIdParams>
  }

我的类中的加载方法如下所示:

  load = <T extends keyof ParamTypes>(target: T, params: ParamTypes[T]["params"]):void => {
    const url = eval('`' + Urls[target] + '`')
    
    // alternative with replace like suggested in a comment
    // this also works with multiple query params
    const url2 = Urls[target].replaceAll(/\$\{(.*?)\}/g, (_: string, k: string) => (params as any)[k])

    // and some code to open that page
  }

这已经有效并确保被调用者提供正确的查询参数(后来我有几十个 URL 目标,并且从很多地方调用了 load 方法,所以值得努力)

我无法解决的部分:我在两个不同的地方使用密钥foo-editor,它映射到“url”的枚举和映射到类型的接口。而且我想保证,枚举和接口都有完全相同的键(比如 - 打字稿应该强制映射并防止拼写错误)。

有没有办法确保这一点?

【问题讨论】:

  • 我真的会使用.replace(/\$\{(.*)\}/g, k =&gt; params[k]);而不是eval
  • 我尝试过 - 但这并不容易,因为我现在必须为 k 找到正确的类型 - 打字稿抱怨。
  • 可能其中一种情况是any 简化了事情(playground
  • 是的,在这里可以接受 - 我已经在方法上设置了类型安全性,所以 params 保证是正确的类型并且将具有所有必需的键。谢谢!
  • @JonasWilms - 我已切换到您的建议,但您的解决方案有两个错误:首先,您的代码中的 k 是完全匹配的 - 第二个是我们想要的捕获值。然后,它只适用于一个参数,因为正则表达式默认是贪婪的。我编辑了我的问题并将可行的替代方案放入其中。感谢您至少为我指明了那个方向!

标签: javascript typescript typescript-generics


【解决方案1】:

您可以将枚举替换为映射类型:

 const Urls: { [K in keyof ParamTypes]: string } = {
   /*...*/
 };

【讨论】:

  • 非常感谢! in keyof 是我缺少的部分。它现在就像一个魅力。
  • @captain 据我所知,每个请求的 ParamType 都不同,因此该类型必须是定义键的类型。
  • @JonasWilms 我的观点主要是关于使用不可变对象而不是枚举。我没有深入提问
  • @captain-yossarian - 我看到了这个添加,并将as const 添加到我的真实代码中。非常有价值!谢谢,我不知道这是可能的
猜你喜欢
  • 2017-08-08
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
  • 2022-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多