1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Typescriptのconst assertionは必ずしも書き換え不可能ではない

Posted at

const assertionとは

Typescript 3.4 から導入された機能。
以下のように記述することで、オブジェクト・配列に対して再帰的に readonly を付与した型として扱ってくれる。

const val1 = {
    value: 'hoge'
};
val1.value = 'fuga'; // これはエラーにならない

const val2 = {
    value: 'hoge'
} as const;

val2.value = 'fuga'; // コンパイルエラー

// as constを使わずに同じことをすると以下になる。
const val3: { readonly value: 'hoge' } = {
  value: 'hoge'
};

val3.value = 'fuga'; // こちらもコンパイルエラー

上記のようにas constを用いることで冗長な型指定をせずにreadonlyを付与、また型のwideningを抑制できる。

readonlyを付与していても書き換えができるパターン

readonlyが付与されていても同じ構造の型でreadonlyが指定されていない型に代入可能なため、
明示的に型のアサーションを行わずとも書き換え可能な型に代入ができる(配列が含まれない場合のみ、配列のときの挙動は後述)

たとえば以下のように。

const cval = { prop1: 'prop1!' } as const;
// cval.prop1 = ''; // これはコンパイルエラー

const val: { prop1: string } = cval; // コンパイルエラーにならない
val.prop1 = 'prop1?';

console.log(cval.prop1); // => prop1?

function f(val: { prop1: string }) {
    val.prop1 = 'prop';
}
f(cval); // これもエラーにならない

console.log(cval.prop1); // => prop

配列が含まれている場合

readonlyがついた配列は動きが違い、readonlyではない配列に型アサーションなしで代入することはできない。

const cval2 = { arry: ['arry1'] } as const;
cval2.arry.push('arry2'); // これはコンパイルエラー

const val2: { arry: string[] } = cval2; // エラーになる

f2(cval2); // これもエラーになる
function f2(val2: { arry: string[] }) {
    val2.arry.push('arry!');
}


const cval3 = ['str1', 'str2'] as const;
cval3.push('str'); // これはコンパイルエラー

const val3: string[] = cval3; // エラーになる

f3(cval3); // これもエラーになる
function f3(val3: string[]) {
    val3.push('str');
}

Object.freezeの場合

Object.freezeの戻り値の型は Readonly<T>なので同様に代入が可能
ただし、実行時にエラーが発生する。

// Object.freezeを使った場合は実行時エラーになる。
const fval = Object.freeze({ prop: 'hoge' });
const val: { prop: string } = fval; // コンパイルエラーにならない
val.prop = 'xxx'; // 実行時にエラーが発生する

参考

1
2
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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?