불변성(immutability)을 사랑하는 라이브러리로 ReactJS가 있는데, Props와 State를 불변하는 것으로 표시할 수 있습니다, 예를 들면:
interfaceProps {readonly foo:number;}interfaceState {readonly bar:number;}exportclassSomethingextendsReact.Component<Props,State> {someMethod() {// 아래와 같은 일이 발생할 수 없음을 확신할 수 있음this.props.foo =123; // 오류: (props는 불변임)this.state.baz =456; // 오류: (this.setState를 사용해야 함) }}
하지만 React의 타입 정의가 이들을 이미 readonly로 표기하고 있기 때문에 직접 이렇게 할 필요는 없습니다 (내부적으로 인자로 전달된 제네릭 타입을 앞서 설명한 Readonly 타입으로 감쌈).
exportclassSomethingextendsReact.Component<{ foo:number }, { baz:number }> {// 아래와 같은 일이 발생할 수 없음을 확신할 수 있음someMethod() {this.props.foo =123; // 오류: (props는 불변임)this.state.baz =456; // 오류: (this.setState를 사용해야 함) }}
이건 JavaScript 네이티브 배열을 불변 스타일로 사용하고자 할 때 아주 편합니다. 사실 TypeScript는 이런 일을 할 수 있도록 ReadonlyArray<T> 인터페이스를 이미 제공하고 있습니다:
let foo:ReadonlyArray<number> = [1,2,3];console.log(foo[0]); // 오케이foo.push(4); // 오류: `push`는 배열을 상태를 바꾸므로 ReadonlyArray에 존재하지 않음foo =foo.concat([4]); // 오케이: 복사본 생성
자동 추론
경우에 따라 컴파일러가 자동으로 특정 항목이 읽기 전용임을 추론해낼 수 있습니다. 즉, 클래스에 속성이 있지만 게터(getter)만 있고 세터(setter)가 없다면 컴파일러는 그 속성을 readonly인 것으로 간주합니다. 예를 들면:
기본적으로 readonly는 내가 속성을 변경하지 못함을 보장하지만, 객체를 다른 사람에게 넘길 경우에는 이것이 보장되지 않고 그 다른 사람은 객체의 속성을 변경할 수 있습니다 (타입 호환성 문제 때문에 허용됨). 물론 iMutateFoo를 foo.bar를 변경하지 않는 함수로 선언했다면 아래에 보이는 것처럼 컴파일러가 올바르게 잘못을 지적할 수 있습니다: