如何将对象键的类型限制为命名空间常量?

bla*_*een 2 namespaces typescript mapped-types

我想定义一个映射类型,其键是命名空间下所有常量的值。

我无法找到涵盖此问题的其他问题。这个问题及其重复讨论了 JavaScript,而我希望对类的属性进行强类型化。我在Typescript handbook中也找不到参考资料。

描述:

我有一个这样的命名空间:

export namespace Controls {
    export const Foo = "foo";
    export const Bar = "bar";
    export const Baz = "baz";
    // ... a dozen others
}
Run Code Online (Sandbox Code Playgroud)

该命名空间不包含任何其他内容。仅那些导出的consts。

我想定义一个对象类型来表达以下含义:“该对象键只能是在该命名空间中声明的 const 值”。天真地像这样:

type Namespaced = { [K in Controls]?: ControlDelegate }

上面的代码无法编译,因为我无法使用命名空间作为类型。由于同样的原因,对类型建立索引也不起作用:

type NamespaceKeys = Controls[keyof typeof Controls]

然后我顿悟了:

{ [K in keyof typeof Controls]?: ControlDelegate }

它确实编译了,解析的类型看起来像我想要的,但是我无法实例化文字:

this.controlDelegates = {
            [Controls.Foo]: new FooControlDelegate() // it implements ControlDelegate
        }
Run Code Online (Sandbox Code Playgroud)

出现以下编译错误:

Type '{ "foo": FooControlDelegate; }' is not assignable to type '{ readonly Foo?: ControlDelegate; ... Object literal may only specify known properties

将对象键的类型限制为某个命名空间下的值的正确方法是什么?

cdi*_*las 5

keyof typeof Controls为您提供的Controls,即“Foo”、“Bar”、“Baz”。你想要的是“foo”,“bar”,“baz”(小写)的Controls

您可以通过 来实现这一点typeof Controls[keyof typeof Controls]