TypeScriptでconstキーワードを使う|応用例も紹介

※本サイトにはプロモーション・広告が含まれています。

(最終更新月:2023年12月)

✔もしあなたが、次のような疑問を抱えているなら、この記事がぴったりです。

「Typescriptでconstをどのように使用するの?」

「const宣言の正しい書き方について知りたい」

「constを使ったTypescriptのコード例を見てみたい」

当記事でお伝えする内容

  • Typescriptにおけるconstの基本的な使い方
  • 変数宣言におけるベストプラクティス
  • TypeScriptでconstを使う実例

具体的なコードスニペットを交えながら、初心者でも理解しやすいようにわかりやすく解説していきます。

Typescriptでの効率的なコーディングを学びたい方は、ぜひ最後までご覧ください。

筆者プロフィール

筆者プロフィールアイコン

【現職】プロダクトマネージャー

【副業】ブログ(月間17万PV)/YouTube/Web・アプリ制作

「プログラミング × ライティング × 営業」の経験を活かし、30後半からのIT系職へシフト。当サイトでは、実際に手を動かせるWebアプリの開発を通じて、プログラミングはもちろん、IT職に必要な情報を提供していきます。

【当ブログで紹介しているサイト】

当サイトチュートリアルで作成したデモ版日報アプリ

Django × Reactで開発したツール系Webアプリ

✔人に見せても恥ずかしくないコードを書こう

「リーダブルコード」は、わかりやすく良いコードの定義を教えてくれる本です。

  • 見るからにきれいなコードの書き方
  • コードの分割方法
  • 変数や関数の命名規則

エンジニアのスタンダートとすべき基準を一から解説しています。

何回も読むのに値する本なので、ぜひ手にとって読んでみてください。

TypeScriptの変数定義基礎

こちらでは、TypeScriptにおける変数定義の基礎についてお伝えしていきます。

変数宣言の基本を理解することで、より構造的で読みやすいコードを書くための礎が築けるでしょう。

  • var、let、constの差異
  • ブロックスコープの説明
  • スコープと変数の寿命

var、let、constの差異

TypeScriptでは、変数を宣言する際にvarletconstの3つのキーワードが使用できます。

varは、ES5までのJavaScriptで一般的に使われてきた方法で、関数スコープを持つキーワード。

ただしvarには、変数の再宣言が可能であるなどの問題点があるため、ES6以降ではletconstが導入されました。

var oldVariable = ""I can be redeclared"";
let newVariable = ""I am block-scoped"";
const constantVariable = ""I cannot be reassigned"";

letはブロックスコープを持ち、変数の再宣言はできませんが、再代入は可能です。

対照的にconstは、初期化時に値を設定した後は再代入ができない、つまり定数として機能するキーワード。

これらの違いを意識することは、安全なコードを書く上で非常に重要です。

ブロックスコープの説明

ブロックスコープとは、変数がその定義されたブロック({}で囲まれた範囲)内でのみアクセス可能であるということ。

letconstはブロックスコープを持っており、これによって変数が意図しない場所からアクセスされるのを防げます。

{
    let blockScopedVariable = ""I exist only in this block"";
}
console.log(blockScopedVariable); // Error: blockScopedVariable is not defined

この例ではblockScopedVariableはブロック内でのみ参照可能であり、外部からはアクセスできません。

ブロックスコープを理解し適切に利用することで、変数の衝突を避け、コードの保守性を高められます。

スコープと変数の寿命

スコープは変数が存在し、参照できる範囲を意味し、変数の寿命はそのスコープに直接関連しています。

  • var: 関数スコープまたはグローバルスコープで有効
  • letconst: 定義されたブロック、ステートメント、または式内でのみ有効

これにより、コード内の異なる部分で同じ名前の変数が独立して使えるようになります。

function exampleFunction() {
    if (true) {
        let scopedVariable = ""I live until the block ends"";
    }
    // scopedVariable is no longer available here
}

変数がどの範囲で有効かを明確にすることで、エラーを減らし、デバッグを容易にします。

確実性のある変数宣言:const

確宜性のある変数宣言とは、読みやすく信頼性の高いコードを書くための変数宣言の方法です。

この方法を用いると、プログラムの各部分が期待した通りに動作することが保証されます。

  • 初期化の必須性と利用例
  • 再代入不能:constの性質とエラー例
  • const変数のベストプラクティス

初期化の必須性と利用例

constで変数を宣言する場合、初期化が必須。

変数が一度設定された後、その値が変更されないことを保証するからです。

不変の参照を作ることで、プログラムの複雑さが減少し、思いがけないバグを防げます。

const greeting = ""Hello, World!"";
console.log(greeting); // ""Hello, World!""
// greeting = ""New Greeting""; // Error: Assignment to constant variable.

greetingが初めに設定された後、再代入しようとするとエラーが発生します。

これがconstの鍵となる特性で、データが予期せず変更されることがないように保証しているのです。

再代入不能:constの性質とエラー例

constは、再代入ができないという性質を持っています。

定義した値を安全に保護するのが役割です。

再代入を試みると、TypeScriptはエラーを投げます。

const pi = 3.14159;
pi = 3.14; // Error: Assignment to constant variable.

constを使用することでプログラミングの意図しない変更を防ぎ、コードの確実性を高めます。

const変数のベストプラクティス

constを使うことが、再代入を意図的に防ぎたい場合のベストプラクティスです。

不変な値の利用は、読み手に対して変数がプログラムの生涯を通じて変わらないことを明示し、コードの予測可能性を高めます。

const MAX_USERS = 100;
const readConfig = () => {
  // config reading logic
};

MAX_USERSはアプリケーションの最大ユーザー数を示し、readConfigは設定を読み込む関数です。

これらの値や関数は再代入されるべきではないため、constを使用するのが良いでしょう。

letとconstの適切な使い分け

変数宣言書でletとconstの正しい使い分けをすることは重要です。

「デフォルトでconst」という宣言スタイルが提唱される一方で、可変性が必要な場合にletを使う適切なケースもあります。

  • シナリオ別:letとconstの選択基準
  • constをデフォルトの選択とすべき理由
  • 可変性が必要な場合のletの利用

シナリオ別:letとconstの選択基準

適切な変数宣言をおこなうためには、その変数がコードの中でどのように扱われるかを理解することが必要です。

たとえば、ループ内でインクリメントされるカウンタや、後で値が更新される可能性のある変数にはletが適切といえるでしょう。

for (let i = 0; i < 10; i++) {
  console.log(i);
}
let userName;
// later
userName = ""New User"";

一方で、再代入がない値や、関数、オブジェクトのプロパティなどにはconstを使うことが推奨されます。

constをデフォルトの選択とすべき理由

constをデフォルトの選択とする最大の理由は、プログラムの予測可能性と信頼性を高めてくれるから。

データの再代入が可能なletよりもconstを使うことで、後から見たときにコードの理解が容易になり、意図しない変更によるバグのリスクを減らせるのです。

可変性が必要な場合のletの利用

しかし、すべての状況でconstが最適とは限りません。

以下のような場面では、letの利用が必要です。

  • 値が変更されることが期待される変数
  • 条件によって値を変えるような場合

たとえば、カウンターや一時的な値保持用の変数などがこれに該当します。

constで保護されないケース

定数であるconstも、すべてのケースで変数の変更を保護するわけではありません

とくに、オブジェクトや配列のように、複雑なデータ構造の場合、constによる再代入の制限を超えた変更が可能です。

以下で、これらのケースに対応する方法について解説します。

  • オブジェクトと配列の可変性
  • readonly属性で不変性を強化
  • 深い不変性の理解と実現
  • constで不可能な場合の代替手段

オブジェクトと配列の可変性

constで宣言されたオブジェクトや配列は、その参照が不変とされますが、その内容まで不変であるわけではありません

プロパティの追加や削除、配列の要素の変更などが許されており、この可変性が問題となる場合もあります。

const user = { name: ""Alice"", age: 25 };
user.age = 26; // This is allowed

この例ではuserオブジェクトのageプロパティを更新できてしまいますが、user自体に新しいオブジェクトを再代入できません。

readonly属性で不変性を強化

TypeScriptには、オブジェクトのプロパティを読み取り専用にするreadonly属性があります。

これを使用することで、オブジェクト内のプロパティが不変であるという意図をより強く表現することができます。

interface User {
  readonly name: string;
  readonly age: number;
}
const user: User = { name: ""Alice"", age: 25 };
user.age = 26; // Error: Cannot assign to 'age' because it is a read-only property.

Userインターフェイスを使ってオブジェクトのプロパティをreadonlyで宣言し、ageプロパティに再代入しようとするとTypeScriptがエラーを出します。

深い不変性の理解と実現

ただし、readonlyはオブジェクトの第一層にしか作用しません。

オブジェクトがネストしている場合は、深いレベルのプロパティも不変であることを保証するために、追加のテクニック(例えば、再帰的にreadonlyを使用する)が必要です。

type ReadOnlyDeep<T> = {
  readonly [P in keyof T]: ReadOnlyDeep<T[P]>;
};

こちらのテクニックを使用することで、オブジェクトの深い部分まで再帰的に読み取り専用プロパティが確保されます。

constで不可能な場合の代替手段

ときにはconstだけで不変性を守るのが難しい場面もあります。

  • ライブラリが内部状態を変更するような場合
  • 外部からのデータ変更がある場面

このような場合は、凍結(Object.freeze)、深いコピー、またはイミュータブルなデータ構造ライブラリの使用を検討することが有効です。

TypeScriptでの高度なconst利用法

TypeScriptを使用すると、constをより高度に活用する方法がいくつかあります。

コードの安全性をさらに高める機能が含まれており、使いこなすことでより堅牢なアプリケーション開発が可能となるでしょう。

  • constアサーションの活用
  • 読み取り専用の配列としての宣言
  • as constの利用シナリオとメリット

constアサーションの活用

constアサーションは、リテラル型を使用する際に役立つ機能です。

TypeScriptにリテラルの値が変更されないことを伝えられます。

const colors = [""red"", ""green"", ""blue""] as const;

このコードでは、colors配列の各要素がリテラルとして扱われ、その型が""red"" | ""green"" | ""blue""と推論されます。

コンパイル時に型エラーを防ぐ強力なメカニズムです。

読み取り専用の配列としての宣言

TypeScriptでは配列をreadonlyとして宣言でき、これにより配列の変更がコンパイル時に防がれます。

const numbers: readonly number[] = [1, 2, 3];
numbers.push(4); // Error: Property 'push' does not exist on type 'readonly number[]'.

readonlyを配列に適用し、配列への変更操作(この場合はpushメソッド)を防いでいます。

as constの利用シナリオとメリット

as const構文は、特定のリテラルをTypeScriptに明示的に””定数””として扱うよう指示するときに使用します。

オブジェクトや配列内の値が不変であると型システムに伝え、より狭い型推論が可能です。

let foo = { bar: 123, baz: ""Hello"" } as const;
// foo's type is now { readonly bar: 123; readonly baz: ""Hello""; }
foo.baz = ""World""; // Error: Cannot assign to 'baz' because it is a read-only property.

この例ではfooのプロパティを読み取り専用として扱い、プロパティの再代入をエラーとしてキャッチしています。

まとめ

当記事では、Typescriptにおけるconstの使い方について学習してきました。

  • varletconstの差異
  • ブロックスコープや変数の寿命の背景知識
  • constで保護されないケース

重要なことは、constを使うことによってプログラムの意図が明確になり、可変性に関する問題を減少させられること。

また、readonlyas constなどTypeScript固有の強力な機能によって、可変性をさらに厳密な制御も可能です。

常にconstを最初の選択肢とし、変更が必要な場合にのみletを使用することを推奨します。

これにより、読みやすく、保守しやすく、そして安全なコードを書くことがより容易になるでしょう。

ぜひ、今回学んだ知識を実際のTypeScriptプログラミングに活かしてみてください。

タイトルとURLをコピーしました