在打字稿中将复杂对象标记为只读

dis*_*nte 0 typescript

我有一个 Angular 服务单例,我将其用作 Vault 来集中有关我的应用程序具有的某些功能的信息。在那里我有一个物体,它是它们真实的唯一来源。

它就像是

enum FeatureEnum {
  SomeFeature = 'SomeFeature',
  SomeOtherFeature = 'SomeOtherFeature'
}


class MyService {
  public featureObjects: Record<FeatureEnum, SomeComplexObjectType> = {
     [FeatureEnum.SomeFeature]: '',// some complex object,
     [FeatureEnum.SomeOtherFeature]: '',// some complex object
   }

  get AsArray()...

  get AsMap()...

  get OtherThings()...
}

Run Code Online (Sandbox Code Playgroud)

我想创建某种映射类型,使所有内容都来自featureObjects打字稿的角度(也就是说,我并不真正关心它在运行时是否可写。尽管拥有它很好)。

使用类似 just 的类型Readonly<MyService>使顶级成员只读。我想要某种“递归”只读。那可能吗?

游乐场链接

jca*_*alz 5

您可能需要像这样的递归映射条件类型:

type DeepReadonly<T> = T extends Function ? T :
  T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]> } :
  T;
Run Code Online (Sandbox Code Playgroud)

T如果它是原始类型或函数,则应该保留它;否则,它会递归地遍历属性,使它们成为readonly属性。我对函数类型进行了特殊处理,因为函数类型的映射往往会产生空类型{}(调用签名不会保留在映射类型中),并且您可能希望能够调用类中的方法。如果这不重要,您可以删除该条款。

无论如何,使用MyService示例代码中的类(并添加一个someMethod()方法来表明该方法仍然有效):

const someInjection = new MyService() as DeepReadonly<MyService>;

someInjection.something = ''; // error, readonly
someInjection.featureObjects.SomeFeature.timeStamp = 1000; // error, readonly
someInjection.featureObjects.SomeFeature.config.name = ''; // error, readonly
someInjection.featureObjects.SomeFeature.config.data.text = ''; // error, readonly
someInjection.someMethod(); // okay
Run Code Online (Sandbox Code Playgroud)

看起来不错。好的,希望有帮助;祝你好运!

Playground 代码链接