TypeScriptで基本型を使用する方法
著者はCOVID-19救済基金を選択し、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
TypeScript は、 JavaScript 言語の拡張であり、コンパイル時の型チェッカーでJavaScriptのランタイムを使用します。 この組み合わせにより、開発者は完全なJavaScriptエコシステムと言語機能を使用できると同時に、オプションの静的型チェック、列挙型データ型、クラス、およびインターフェースを追加できます。 これらの機能は、JavaScriptの動的な性質の柔軟性を開発者に提供しますが、コンパイル時に型情報を使用して、実行時にバグやその他の予期しない動作を引き起こす可能性のある問題を検出できる、より信頼性の高いコードベースも可能にします。
追加のタイプ情報は、コードベースのより優れたドキュメントと、テキストエディターでの改善された IntelliSense (コード補完、パラメーター情報、および同様のコンテンツ支援機能)も提供します。 チームメイトは、実装自体を実行しなくても、変数または関数パラメーターにどのタイプが期待されるかを正確に特定できます。
このチュートリアルでは、型宣言とTypeScriptで使用されるすべての基本型について説明します。 さまざまなコードサンプルの例を紹介します。これは、独自のTypeScript環境、またはブラウザで直接TypeScriptを記述できるオンライン環境である TypeScriptPlaygroundで実行できます。
前提条件
このチュートリアルに従うには、次のものが必要です。
- TypeScriptプログラムを実行して、例に従うことができる環境。 これをローカルマシンに設定するには、次のものが必要になります。
TypeScript関連のパッケージを処理する開発環境を実行するためにインストールされたNodeとnpm(またはyarn)の両方。 このチュートリアルは、Node.jsバージョン14.3.0およびnpmバージョン6.14.5でテストされました。 macOSまたはUbuntu18.04にインストールするには、「Node.jsをインストールしてmacOSにローカル開発環境を作成する方法」または「Ubuntu18.04にNode.jsをインストールする方法」の「PPAを使用したインストール」セクションの手順に従います。 これは、Windows Subsystem for Linux(WSL)を使用している場合にも機能します。 さらに、TypeScriptコンパイラ(tsc)がマシンにインストールされている必要があります。 これを行うには、TypeScriptの公式Webサイトを参照してください。 - ローカルマシン上にTypeScript環境を作成したくない場合は、公式の TypeScriptPlaygroundを使用してフォローできます。
- JavaScript、特に destructuring、rest演算子、 imports /exportsなどのES6+構文に関する十分な知識が必要です。 これらのトピックに関する詳細情報が必要な場合は、JavaScriptシリーズのコーディング方法を読むことをお勧めします。
- このチュートリアルでは、TypeScriptをサポートし、インラインエラーを表示するテキストエディタの側面を参照します。 これはTypeScriptを使用するために必要ではありませんが、TypeScript機能をさらに活用します。 これらの利点を活用するには、 Visual Studio Code のようなテキストエディターを使用できます。このエディターは、TypeScriptをすぐにサポートします。 TypeScriptPlaygroundでこれらの利点を試すこともできます。
このチュートリアルに示されているすべての例は、TypeScriptバージョン4.2.2を使用して作成されています。
TypeScriptでの変数型の宣言
純粋に動的な言語であるJavaScriptでコードを記述する場合、変数のデータ型を指定することはできません。 次に示すように、変数を作成して値を割り当てますが、タイプは指定しないでください。
const language = {
name: "JavaScript"
};
このコードブロックでは、language
はプロパティname
の文字列値を保持するオブジェクトです。 language
の値型とそのプロパティは明示的に設定されていないため、将来の開発者がlanguage
が参照する値の種類がわからない場合、後で混乱が生じる可能性があります。
TypeScriptには、主な利点として厳密な型システムがあります。 静的に型付けされた言語は、コンパイル時に変数の型がわかっている言語です。 このセクションでは、TypeScriptで変数タイプを指定するために使用される構文を試してみます。
タイプは、コードに直接書き込む追加情報です。 TypeScriptコンパイラは、この追加情報を使用して、タイプに応じて異なる値を正しく使用するように強制します。
JavaScriptなどの動的言語を操作し、string
変数をnumber
のように使用することを想像してみてください。 strict
単体テストがない場合、考えられるバグは実行時にのみ発生します。 TypeScriptで使用可能な型システムを使用している場合、コンパイラはコードをコンパイルせず、代わりに次のようなエラーが発生します。
OutputThe right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. (2363)
TypeScriptで特定のタイプの変数を宣言するには、次の構文を使用します。
declarationKeyword variableName: Type
declarationKeyword
は、let
、var
、またはconst
のようになります。 この後に、変数名、コロン(:
)、およびその変数のタイプが続きます。
TypeScriptで記述したコードは、型を指定していなくても、何らかの方法ですでに型システムを使用しています。 このコードを例として取り上げます。
let language = 'TypeScript';
TypeScriptでは、これは次と同じ意味を持ちます。
let language: string = 'TypeScript';
最初の例では、language
変数の型をstring
に設定しませんでしたが、宣言時に文字列値を割り当てたため、TypeScriptは型を推測しました。 2番目の例では、language
変数のタイプをstring
に明示的に設定しています。
let
の代わりにconst
を使用した場合、次のようになります。
const language = 'TypeScript';
この場合、TypeScriptは、次のように入力した場合と同様に、文字列リテラルTypeScript
を変数の型として使用します。
const language: 'TypeScript' = 'TypeScript';
TypeScriptがこれを行うのは、 const を使用する場合、宣言後に変数に新しい値を割り当てないためです。これを行うとエラーが発生するためです。
注: TypeScriptをサポートするエディターを使用している場合、カーソルで変数にカーソルを合わせると、各変数のタイプ情報が表示されます。
変数のタイプを明示的に設定し、その値として別のタイプを使用する場合、TypeScriptコンパイラー(tsc
)またはエディターはエラー2322
を表示します。 次のコマンドを実行してみてください。
const myNumber: number = 'look! this is not a number :)';
これにより、次のエラーが発生します。
OutputType 'string' is not assignable to type 'number'. (2322)
TypeScriptで変数の型を設定してみたので、次のセクションでは、TypeScriptでサポートされているすべての基本的な型を示します。
TypeScriptで使用される基本的なタイプ
TypeScriptには複数の基本的なタイプがあり、より複雑なタイプを構築するときにビルディングブロックとして使用されます。 次のセクションでは、これらのタイプのほとんどを調べます。 このセクション全体で作成しているほとんどの変数は、TypeScriptがそれらを推測できるため、型を省略できることに注意してください。ただし、学習目的で型について明示していることに注意してください。
string
タイプstring
は、文字列リテラルやテンプレート文字列などのテキストデータ型に使用されます。
次のコードを試してください。
const language: string = 'TypeScript';
const message: string = `I'm programming in ${language}!`;
このコードブロックでは、language
とmessage
の両方にstring
タイプが割り当てられています。 テンプレートリテラルは、動的に決定されますが、文字列のままです。
文字列はJavaScriptプログラミングで一般的であるため、これはおそらく最も使用するタイプの1つです。
boolean
タイプboolean
は、true
またはfalse
を表すために使用されます。
次のブロックのコードを試してください。
const hasErrors: boolean = true;
const isValid: boolean = false;
hasErrors
とisValid
はブール値として宣言されているため、値true
とfalse
のみを割り当てることができます。 truthyおよびfalsyの値は同等のブール値に変換されず、これらの変数とともに使用するとエラーがスローされることに注意してください。
number
タイプnumber
は、次のように整数と浮動小数点数を表すために使用されます。
const pi: number = 3.14159;
const year: number = 2021;
これはJavaScript開発で頻繁に使用されるもう1つの一般的なタイプであるため、この宣言はTypeScriptで一般的になります。
bigint
タイプbigint
は、ES2020を対象とする場合に使用できるタイプです。 BigInt を表すために使用されます。これは、2^53
より大きい整数を格納するための新しいデータ型です。
次のコードを試してください。
const bigNumber: bigint = 9007199254740993n;
注:このコードがエラーをスローする場合、TypeScriptがターゲットES2020
に設定されていない可能性があります。 これは、tsconfig.jsonファイルで変更できます。
2^53
より大きい数値または一部の数学ライブラリを使用している場合は、bigint
が一般的な型宣言になります。
symbol
symbol
タイプは、Symbolプリミティブ値を表すために使用されます。 これにより、名前のない一意の値が作成されます。
Symbol()
コンストラクター関数を使用して、次のコードを実行します。
const mySymbol: symbol = Symbol('unique-symbol-value');
これらの値の一意性を使用して、参照の衝突を回避できます。 JavaScriptのシンボルの詳細については、Mozilla Developer Network(MDN)のシンボルの記事を参照してください。
配列
TypeScriptでは、配列は、期待される要素に基づいて型指定されます。 配列を入力するには、次の2つの方法があります。
- 予想されるタイプの配列要素に
[]
を追加します。 たとえば、複数のnumber
値を保持する配列を入力する場合は、次のように実行できます。
const primeNumbers: number[] = [2, 3, 5, 7, 11];
この配列に文字列値を割り当てた場合、TypeScriptはエラーを出します。
Array<T>
Genericを使用します。ここで、T
は、その配列内の要素の予想されるタイプです。 前の例を使用すると、次のようになります。
const primeNumbers: Array<number> = [2, 3, 5, 7, 11];
どちらの方法も同じなので、どちらかを選択して、その形式のみを使用して配列を表現してみてください。 これにより、コードベースの一貫性が保たれます。これは、多くの場合、一方のスタイルを他方よりも選択するよりも重要です。
TypeScriptで配列を保持する変数を使用する際の重要な側面の1つは、ほとんどの場合、それらを入力する必要があるということです。 次のコードを試してください。
const myArray = [];
TypeScriptは、この配列で予期される正しい型を推測できません。 代わりに、any[]
を使用します。これは、あらゆるものの配列を意味します。 これはタイプセーフではなく、コードの後半で混乱を引き起こす可能性があります。
コードをより堅牢にするために、配列のタイプについて明示的にすることをお勧めします。 たとえば、これにより、配列に数値要素が含まれるようになります。
const myArray: number[] = [];
このように、無効な値を配列にプッシュしようとすると、TypeScriptはエラーを生成します。 次のコードを試してください。
const myArray: number[] = [];
myArray.push('some-text');
TypeScriptコンパイラはエラー2345
を表示します:
OutputArgument of type 'string' is not assignable to parameter of type 'number'. (2345)
タプル
タプルは、特定の数の要素を持つ配列です。 この一般的な使用例の1つは、2D座標を[x, y]
の形式で保存することです。 React を使用していて、フックを使用している場合、ほとんどのフックの結果もconst [isValid, setIsValid] = React.useState(false)
のようにタプルになります。
タプルを入力するには、配列を入力するときとは対照的に、要素の型を[]
で囲み、コンマで区切ります。 要素のタイプを使用してリテラル配列を作成していると想像してください。
const position: [number, number] = [1, 2];
タプルが期待する要素の数より少ない、または多い数を渡そうとすると、TypeScriptコンパイラはエラー2322
を表示します。
たとえば、次のコードを考えてみましょう。
const position: [number, number] = [1, 2, 3];
これにより、次のようになります。
OutputType '[number, number, number]' is not assignable to type '[number, number]'.
Source has 3 element(s) but target allows only 2. (2322)
any
値がサードパーティのライブラリからのものであるか、TypeScriptなしで最初に記述されたコードからのものであるかなど、特定の状況では、値のタイプを指定するのが難しい場合があります。 これは、JavaScriptコードベースを小さなステップでTypeScriptに移行する場合に特に一般的です。 これらのシナリオでは、any
と呼ばれる特別なタイプを使用できます。これは、任意のタイプを意味します。 any
を使用することは、型チェックをオプトアウトすることを意味し、TypeScriptコンパイラにその値を無視させることと同じです。
次のコードブロックを取ります。
let thisCanBeAnything: any = 12345;
thisCanBeAnything = "I can be anything - Look, I'm a string now";
thisCanBeAnything = ["Now I'm an array - This is almost like pure JavaScript!"];
タイプがany
として宣言されているため、これらの宣言はいずれもTypeScriptでエラーを発生させません。
注:ほとんどの場合、可能であれば、any
の使用は避けてください。 これを使用すると、TypeScriptの主な利点の1つである静的に型指定されたコードが失われます。
unknown
unknown
タイプは、any
タイプのタイプセーフな対応物のようなものです。 unknown
は、の値を判別できないものを入力したいが、その値を使用するコードが使用する前にタイプを正しくチェックしていることを確認したい場合に使用できます。 これは、ユーザーからの幅広い値を受け入れる可能性があり、値を明示的に入力したくないライブラリ内の関数を持つライブラリ作成者にとって便利です。
たとえば、code
という変数がある場合:
let code: unknown;
その後、プログラムの後半で、35
(number
)などの異なる値、または配列やオブジェクトなどの完全に無関係な値をそのフィールドに割り当てることができます。
注: let を使用しているのは、その変数に新しい値を割り当てるためです。
同じコードの後半で、code
を数値に設定できます。
code = 35;
しかし、後でそれを配列に割り当てることができます。
code = [12345];
オブジェクトに再割り当てすることもできます。
code = {};
コードの後半で、その値を他のnumber
と比較する場合は、次のようになります。
const isCodeGreaterThan100 = code > 100;
TypeScriptコンパイラはエラー2571
を表示します。
OutputObject is of type 'unknown'. (2571)
これは、code
がunknown
タイプではなく、number
タイプである必要があるために発生します。 タイプunknown
の値で操作を行う場合、TypeScriptは、タイプが予期したものであることを確認する必要があります。 これを行う1つの例は、JavaScriptにすでに存在するtypeof
演算子を使用することです。 次のコードブロックを調べます。
if (typeof code === 'number') {
const isCodeGreaterThan100 = code > 60;
// ...
} else {
throw new Error('Invalid value received as code');
}
この例では、code
がtypeof
演算子を使用して数値であるかどうかを確認しています。 これを行うと、TypeScriptは変数のタイプをそのif
ブロック内のnumber
に強制します。これは、実行時にif
内のコードが含まれるためです。 ]ブロックは、code
が現在数値に設定されている場合にのみ実行されます。 そうしないと、渡された値が無効であるというJavaScriptエラーがスローされます。
unknown
タイプとany
タイプの違いを理解するために、unknown
を「その値のタイプがわからない」およびany
と考えることができます。 「この値がどのタイプを保持するかは関係ありません」として。
void
void
型を使用して、問題の変数を型をまったく保持しないものとして定義できます。 値を返さない関数の結果を変数に割り当てると、その変数の型はvoid
になります。
次のコードを取ります。
function doSomething() {};
const resultOfVoidFunction: void = doSomething();
TypeScriptでvoid
タイプを直接使用する必要はほとんどありません。
null
およびundefined
TypeScriptのnull
とundefined
の値には、同じ名前で呼び出される独自のタイプがあります。
const someNullField: null = null;
const someUndefinedField: undefined = undefined;
これらは、このシリーズの後半で説明する独自のカスタムタイプを作成するときに特に役立ちます。
never
never
タイプは、決して存在しない値のタイプです。 たとえば、数値変数を作成するとします。
const year: number = 2021;
year
がnumber
でない場合に、if
ブロックを作成してコードを実行すると、次のようになります。
if (typeof year !== "number") {
year;
}
そのif
ブロック内の変数year
のタイプは、never
になります。 これは、year
がnumber
と入力されているため、このif
ブロックの条件が満たされないためです。 never
型は、この時点ではその変数に値を設定できないため、不可能な型と考えることができます。
object
object
型は、プリミティブ型ではないすべての型を表します。 これは、次のいずれのタイプでもないことを意味します。
number
string
boolean
bigint
symbol
null
undefined
object
タイプは、オブジェクトリテラルを記述するために一般的に使用されます。これは、任意のオブジェクトリテラルを割り当てることができるためです。
const programmingLanguage: object = {
name: "TypeScript"
};
注:この場合に使用できるobject
よりもはるかに優れたタイプがあり、Record
と呼ばれます。 これはカスタムタイプの作成と関係があり、このシリーズの後のチュートリアルで説明されています。
結論
このチュートリアルでは、TypeScriptで使用できるさまざまな基本タイプを試しました。 これらのタイプは、TypeScriptコードベースで作業するときに頻繁に使用され、より複雑なカスタムタイプを作成するための主要な構成要素です。
TypeScriptのその他のチュートリアルについては、TypeScriptシリーズのコーディング方法ページをご覧ください。