【问题标题】:How to infer computed object keys in TypeScript如何在 TypeScript 中推断计算对象键
【发布时间】:2022-06-10 23:56:33
【问题描述】:

我正在创建一个项目,我想在其中轻松定义新插件,并且我想在我的 IDE 中使用 TypeScript 来帮助我使用这些插件的名称。我有一个这样的文件夹结构:

src
│ ...
└── plugins
   └── pluginA
   |     index.ts
   └── pluginB
   |     index.ts
   └── ...
     index.ts <-- "here I want to combine all plugins in one object"

每个插件在index.ts 中都有一个默认导出,接口如下:

interface Plugin {
  name: string
  ...
}

src/plugins/pluginA/index.ts

export default {
  name: "pluginA",
  ...
}

src/plugins/index.ts

import pluginA from "./pluginA"
import pluginB from "./pluginB"
...

export default {
  [pluginA.name]: pluginA
  [pluginB.name]: pluginB
  ...
}

并且我希望 TypeScript 了解现有插件的名称(以推断插件键的字面量类型)。

换句话说,我想在我的代码中使用这样定义的插件:

import plugins from "src/plugins"

...

const plugin = plugins["nonExistingPlugin"] // I want the typescript to show error here, since there is no plugin with this name
//                     ~~~~~~~~~~~~~~~~~~~

const anotherPlugin = plugins["plug_"] // I want the IDE to autocomplete the name of the plugin from the existing ones
//                            "pluginA"
//                            "pluginB"
//                            "..."

我的所有尝试都让我发现,TypeScript 理解插件的name 属性是string,但没有推断出文字类型。

TypeScript 可以做到这一点吗?如果没有,还有其他方法可以实现吗?

【问题讨论】:

  • 你试过as const:export default { ... } as const吗?
  • @RobbyCornelissen,是的,我做到了,但可能是以错误的方式。我到底应该把as const放在哪里?
  • 忽略我的评论。在这种情况下,const 断言将不起作用,除非您定义所有内容(即所有插件对象和插件对象)as const

标签: typescript


【解决方案1】:

您可以在此处使用as const 断言:

const pluginA = {
  name: 'pluginA',
  //
} as const
const pluginB = {
  name: 'pluginB',
  //
} as const
const pluginC = {
  name: 'pluginC',
  //
} as const

const plugins = {
  [pluginA.name]: '',
  [pluginB.name]: '',
  [pluginC.name]: '',
}
const plugin = plugins["nonExistingPlugin"] 

// Gives me a type error as expected
// Element implicitly has an 'any' type because expression of type '"nonExistingPlugin"' can't be used to index type '{ pluginA: string; pluginB: string; pluginC: string; }'.
//  Property 'nonExistingPlugin' does not exist on type '{ pluginA: string; pluginB: string; pluginC: string; }'.ts(7053)
const plugin = plugins["plugin"] // Editor shows autocompletes for `pluginA`, `pluginB`, `pluginC`

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-09
    • 2019-03-31
    • 2020-12-28
    • 2019-07-03
    • 2019-02-04
    • 2020-01-29
    • 2020-02-15
    相关资源
    最近更新 更多