1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Type Script】read only な list の宣言

Posted at

結論からいえ


class Hoge {

    constructor(
        // どちらでも可能
        private readonly mylist: readonly string[]
        public readonly mylist2: readonly string[]
    ){
    
    }
}

詳しく

readonly属性への理解

リストは基本的に「順番が保証されていて、操作可能な可変長の集合」を使いたいときに使うものです。
なので操作可能な事自体は必要なことなのですが…
まれに、このリストそのものを使わせてもよいが、変更は加えてほしくない、という場面に遭遇します。
そして思いつくのがこれです。


class Hoge {

    constructor(
        public readonly mylist: string[]
    ){
    
    }
}

これでreadonlyなリストが宣言できました、というわけにはいきません。


class Hoge {

    constructor(
        public readonly mylist: string[]
    ){
    
    }
}

const hoge = new Hoge(["0", "1", "2"])
hoge[0] = "3"

console.log(hoge)
// "3", "1", "2"

はい、mylistは普通に変更できてしまいます。
対して、これはエラーとなります。

class Hoge {

    constructor(
        public readonly mylist: string[]
    ){
    
    }
}

const hoge = new Hoge(["0", "1", "2"])
hoge.mylist = ["3", "1", "2"] // error!

このことから、readonly属性はリスト内部の変更を制限しないことがわかります。
あくまで、その変数そのもの(今回はmylist)を変更することを制限するにとどまります。

readonly T[]

readonly T[]として宣言することで、typescriptコンパイラに、破壊的動作をするメソッドを
このlistは持たない、ということを宣言します。

class Hoge {

    constructor(
        public readonly mylist: readonly string[]
    ){
    
    }
}

const hoge = new Hoge(["0", "1", "2"])
hoge.mylist[0] = ["3"] // error!
hoge.mylist.push("4") //error!

これにより、mylistが外部から汚染されることを免れます。

注意点

readonly T[]はあくまでコンパイラに、破壊的メソッドが存在しないことを宣言する(隠す)だけであり、
強引に実行すると普通に実行される点に気をつけてください。
また、readonlyは再帰的ではありません。list内のオブジェクトがミュータブルな実装をしている場合、
値が変更されます。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?