LoginSignup
1
1

More than 3 years have passed since last update.

Objectの子要素までimmutable/readonlyにする

Posted at

tl;dr

const variable = <element> as const の形で定義する

// object
const immutableObj = {
    a: 1,
    b: "test message",
    inner: { key: "foo" },
  } as const;
// =>型
// const immutableObj: {
//    readonly a: 1;
//    readonly b: "test message";
//    readonly inner: {
//        readonly key: "foo";
//    };
// }

const immutableList = [1, "test message", ['inner']] as const;
// => 型
// const immutableList: readonly [1, "test message",
//            readonly ["inner"]
//       ]

as const

  • ネストされた子要素までreadonlyになる
    • 上記だとinnerの箇所
  • リテラル型が使われる
    • 上記だとb: stringでなくて、b: "test message"型になる
  • TypeScriptレイヤーの話なのでトランスパイルされたJSには何も影響がない
    • (左TS、右トランスパイルされたJS)memo.png
  • Classはas constできない。なので、Object.freezeを使うか、クラスプロパティにreadonlyを指定する(後述)

Object.freeze

Object.freeze() - JavaScript | MDN

      const mutableObj = { a: 1, b: "test message", inner: { key: "foo" } };
      const freezed = Object.freeze(mutableObj);
      freezed.b = 'dar'          // ERROR
      freezed.inner.key = "bar"; // SUCCESS
  const freezed = Object.freeze(
     { a: 1, b: "test message", inner: { key: "foo" } }
  );
  // => 型
  // const freezed: Readonly<{
  //  a: number;
  //  b: string;     << stringでなくて'test message'型であってほしい
  //  inner: {
  //      key: string;
  //  };
  //}>
  • Classでは as const でなくて Object.freeze が使える。
    • ただ、nestしたオブジェクトに対するfreezeがガバガバなので注意
  class Person {
    public obj: { a: number; b: string, inner: {key: string} };
    constructor() {
      this.obj = { a: 1, b: "hello world", inner: {key: 'foo'} };
    }
  }
  const p = new Person();

  const freezed = Object.freeze(p);
  freezed.obj = {...freezed.obj, b: 'bar1'}; // ERROR TS-2540
  freezed.obj.b = 'new bar';                 // SUCCESS
  freezed.obj.inner = {key: 'bar' };         // SUCCESS

まとめ

  • 極力 as const を使う
  • Class のときは仕方ないので Object.freeze を使う
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1