개발/Front-End

TypeScript 에서 Object 타입 readonly 설정

날고싶은병아리 2022. 7. 25. 11:36

TypeScript 에는 타입을 읽기 전용으로 만들어주는 타입 시스템이 있다.

 

type ObjectType = {
  property1: number;
  readonly property2: number;
};

const object: ObjectType = {
  property1: 1,
  property2: 2,
};

object.property1 = 11;
object.property2 = 22; // 에러 발생

이런 식으로 말이다.

 

type ObjectType = Readonly<{
  property1: number;
  property2: number;
}>;

const object: ObjectType = {
  property1: 1,
  property2: 2,
};

object.property1 = 11; // 에러 발생
object.property2 = 22; // 에러 발생

모든 속성에 대해 읽기 전용으로 만드는 방식은 Readonly 타입을 사용하면 된다.

하지만 중첩된 구조를 가진 Object 일 경우는 어떻게 될까?

 

type ObjectType = Readonly<{
  property1: number;
  property2: {
    property2a: number;
    property2b: number;
  };
}>;

const object: ObjectType = {
  property1: 1,
  property2: {
    property2a: 21,
    property2b: 22,
  },
};

object.property1 = 11; // 에러 발생
object.property2.property2a = 221;
object.property2.property2b = 222;

Readonly 타입을 사용해도 재귀적으로 읽기 전용 속성이 지정되지 않는다.

 

 

https://stackoverflow.com/questions/41879327/deepreadonly-object-typescript

 

DeepReadonly Object Typescript

It is possible to create a DeepReadonly type like this: type DeepReadonly<T> = { readonly [P in keyof T]: DeepReadonly<T[P]>; }; interface A { B: { C: number; }; D: { E: number;...

stackoverflow.com

 

역시 구글과 스택 오버플로우에는 없는 게 없다.

 

// @types/global.d.ts

export { global };

declare global {
  type DeepReadonly<T> = T extends (infer R)[]
    ? DeepReadonlyArray<R>
    : T extends object
    ? DeepReadonlyObject<T>
    : T;
  interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
  type DeepReadonlyObject<T> = {
    readonly [P in keyof T]: DeepReadonly<T[P]>;
  };
}

DeepReadonly 같이 재귀적인 읽기 전용 속성을 하나 만들어 두면 된다.

 

type ObjectType = DeepReadonly<{
  property1: number;
  property2: {
    property2a: number;
    property2b: number;
  };
}>;

const object: ObjectType = {
  property1: 1,
  property2: {
    property2a: 21,
    property2b: 22,
  },
};

object.property1 = 11; // 에러 발생
object.property2.property2a = 221; // 에러 발생
object.property2.property2b = 222; // 에러 발생

중첩된 구조의 config 파일 등을 유지 보수할 때 아주 유용하다.

 

항상 구글에 감사하십시오. 휴먼.