【问题标题】:Can I map a string literal to a type of types?我可以将字符串文字映射到一种类型吗?
【发布时间】:2023-02-07 12:47:47
【问题描述】:

我有一个字符串文字类型,例如

type ConfigurationTypes = 'test' | 'mock'

和一些类型

type MockType = { id: string }
type TestType = { code: string }

我想创建一个类型,将字符串文字“映射”到这种类型,这样如果 ConfigurationTypes 发生变化,我的类型 MappedConfigurationTypes 也需要相应地改变。有可能吗?

type MappedConfigurationTypes: {[key in ConfigurationTypes]: any} = {
  test: TestType
  mock: MockType
}

【问题讨论】:

  • this approach 是否满足您的需求?如果是这样,我可以写一个答案来解释;如果没有,我错过了什么?
  • @jcalz 是的!拜托,如果你能解释一下,我从来没有见过这样使用这个“扩展”,好吧,我的搜索分支到更高级的类型,但这会很好用
  • 当我有机会时,我会写一个答案。
  • 不用担心,这段摘录已经解决了我过去几个小时一直试图解决的问题,非常感谢,希望你今天(或晚上)过得愉快!

标签: typescript typescript-generics


【解决方案1】:

从某种意义上说,您正在寻找类型级别的satisfies operator。如果你写 e satisfies T,其中 e 是某种表达式,T 是某种类型,编译器将确保 e可分配的T 没有拓宽T,所以 e 保留其原始类型,但如果与 T 不兼容,您将收到错误消息。你想做同样的事情,但用另一种类型替换表达式。就像是

// this is invalid TS, don't do this:
type MappedConfigurationTypes = {
  test: testType; 
  mock: MockType
} Satisfies {[K in ConfigurationTypes]: any}

但是没有这样的 Satisfies 类型运算符。太糟糕了。


幸运的是,我们基本上可以自己构建一个:而不是T Satisfies U,我们可以编写Satisfies<U, T>(我将“Satisfies U”作为注释的句法单元,所以这就是为什么我想要Satisfies<U, T>而不是Satisfies<T, U>。但是您可以根据需要定义它)。

这是定义:

type Satisfies<U, T extends U> = T;

您可以看到 Satisfies&lt;U, T&gt; 将始终计算为 T,但由于 TconstrainedU,如果 TU 不兼容,编译器将报错。


让我们试试看:

type ConfigurationTypes = 'test' | 'mock';
type MockType = { id: string }
type TestType = { code: string }        

type MappedConfigurationTypes = Satisfies<{ [K in ConfigurationTypes]: any }, {
    test: TestType
    mock: MockType
}>    

看起来不错。如果将鼠标悬停在 MappedConfigurationTypes 上,您会看到它等同于

/* type MappedConfigurationTypes = {
    test: TestType;
    mock: MockType;
} */

另一方面,如果您将另一个成员添加到 ConfigurationTypes union,您将看到所需的错误:

type ConfigurationTypes = 'test' | 'mock' | 'oops'

type MappedConfigurationTypes = Satisfies<{ [K in ConfigurationTypes]: any }, {
    test: TestType
    mock: MockType,
}> // error!
//   Property 'oops' is missing in type '{ test: TestType; mock: MockType; }' but required 
//   in type '{ test: any; mock: any; oops: any; }'.

Playground link to code

【讨论】:

    猜你喜欢
    • 2021-01-14
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 2021-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多