TypeScript-如何为具有未知键的深度不同的对象映射只读接口?

时间:2019-08-20 11:51:44

标签: typescript

目前在我的应用程序中,我的常量位于一个导出的const对象中,该常量位于多个文件中,具体取决于它们所在的库。这些对象的深度未知,尽管就目前所有意图和目的而言,最大深度是2。键始终是一个字符串,值也始终是一个字符串。

我想通过接口或其他方式将它们设置为只读(由于需要polyfill,因此理想情况下没有库或Object.freeze)。由于这些文件会一直在变化,因此我觉得映射接口内的每个嵌套对象以及进行大量工作是不明智的。

最初,我尝试创建一个递归接口,希望它可以工作:

interface ConstantsInterface {
  readonly [field: string]: string | ConstantsInterface;
}

const CONSTANTS_MAIN: ConstantsInterface = {
    key1: 'val1',
    key2: 'val2',
    key3: {
        key4: 'val4,
        key5: {
           key6: 'val6',
           key7: 'val7'
         }
    },
    key8: 'key8'
}

...等等。请记住,此结构只是一个示例,实际上并不严格。即在给定对象的任何位置都可以有任意数量的条目。

此接口未按计划工作,并导致某些键抛出许多“类型ConstantsInterface无法应用于key1类型”或“类型[field:string]无法应用于key2类型”等。

然后我尝试尝试绘制深度,因为我觉得这是问题所在(尽管我不应该这样,因为理论上深度可以是任意大小):

interface ConstantsInterface {
  readonly [field: string]: string | readonly [field: string]: { 
  readonly [field: string] | string };
}

等,虽然确实解决了上述错误的某些情况,但最终却在其他地方弹出。

我对TypeScript还是比较陌生,我认为答案就在于泛型(或完全不同的结构,例如名称空间),但我不知道如何应用这种东西。 谢谢

1 个答案:

答案 0 :(得分:4)

我不会创建通用的接口来描述您的常量,而是依靠推断的常量类型,并使用as const assertion将其设为只读。

const CONSTANTS_MAIN = {
    key1: 'val1',
    key2: 'val2',
    key3: {
        key4: 'val4',
        key5: {
           key6: 'val6',
           key7: 'val7'
         }
    },
    key8: 'key8'
} as const;

生成的CONSTAINTS_MAIN类型将具有所有readonly属性和特定值。

您可以使用类型别名和typeof为类型命名:

type MainConstants = typeof CONSTANTS_MAIN;