TypeScriptの重要な機能である「型」について学びましょう!
環境構築
以下の記事で作成したプロジェクトを使います。
※TypeScriptが動けば問題ありません
型の種類
型 | 内容 | 例 |
---|---|---|
number | 整数や浮動小数点を含む整数値 | 1, 30.3, -5 |
string | 全ての文字列 | ‘I’, “My” |
boolean | 真偽値 | true or false |
object | JavaScriptのObject型 | {name: “selfnote”} |
Array | JavaScriptのArray型 | [1, 2, 3] |
Tuple | TypeScriptの独自の型: 固定長 | [1, 2] |
Enum | TypeScriptの独自の型: 列挙型 | enum { NEW, OLD } |
any | どんな型でも良い。型を指定しない。 | *(アスタリスク) |
TypeScriptで型を利用する方法
まずは、通常のJavaScriptを書いてみます。
1 2 3 4 5 6 7 |
// 合計を計算する関数 function sum(num1, num2) { return num1 + num2; } const result = sum(1, 2); console.log(result) |
これは単純な例ですが、TypeScriptの便利さを実感するのに役立ちます。
上記の出力結果は、「3」になります。
しかし、以下の場合はどうなるでしょうか。
1 |
const result = sum("1", 2); |
引数の一つをstring型にしました。JavaScriptの場合、Typeが異なっていてもエラーを発生させずに処理をします。
結果は以下のようになります。
1 |
12(string型) |
これは、明らかなバグです。JavaScriptはこういうところがめんどくさいのです。
しかし、TypeScriptの型定義を活用すれば、この問題は解決されます。
1 2 3 4 5 6 7 |
// 合計を計算する関数 function sum(num1:number, num2:number) { return num1 + num2; } const result = sum(1, 2); console.log(result) |
sum関数の引数に型を追加しました。TypeScriptではこのように「:type」で型を指定します。
型にはnumber型を指定したので、sum関数に「数値以外」受け付けなくなりました。
例えば、先ほどの例のように引数の一つをstring型にすると、以下のエラーメッセージが表示されます。
1 |
Argument of type '"1"' is not assignable to parameter of type 'number'.ts(2345) |
補足) 型の大文字・小文字
Typscriptでは、stringやnumberのような小文字で型を指定します。StringやNumberなどの大文字ではありません。
型推論(TypInference)
TypeScriptには、型推論と呼ばれる型を自動的に判断する機能が備わっています。
先ほどのサンプルから例に挙げると、result変数の部分がそれに当たります。
1 2 |
# number型と推論している const result = sum(1, 2); |

resultには、number型が入るとTypeScriptが判断しており、そしてそれは正しいです。
TypeScriptが正しく型を推論する場合は、型を指定しないほうが良いです。
1 2 |
# 以下の書き方も可能だが、やらなくて良い const result: number = sum(1, 2) |
Tuple型について
Tuple型は長さが固定化されている配列です。
JavaScriptにはない型なので、使い方をみてみましょう。
Personオブジェクトを定義して、Tupleを設定してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const person: { name: string, // string型 age: number, // number型 isMen: boolean // boolean型 hobbies: string[] // Array型 info: [number, string] // Tuple型 } = { name: 'selfnote', age: 31, isMen: true, hobbies: ["Sports", "Investiments"], info: [1, "Web Develper"] // Tuple } |
オブジェクトに型を定義するときは、 変数名に「: {}」をつけます。
そして、Tupleにする場合は、[“type”]を指定します。Array型と指定方法が異なることがわかると思います。
Enum型について
TypeScriptでは、Enum型を設定することが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
enum Role { ADMIN, READ_ONLY, AUTHOR, } const person = { name: 'selfnote', age: 31, role: Role.ADMIN } if (person.role === Role.ADMIN) { console.log('Admin User') } |
Union型について
型指定には、2つ以上の型を指定することが可能です。
1 2 3 4 5 6 7 8 9 |
function combine(arg1:number | string, arg2:number | string) { if (typeof arg1 === 'number' && typeof arg2 === 'number') { return arg1 + arg2; } return `Hello, ${arg1}, ${arg2}` } console.log(combine(10, 20)); console.log(combine("selfnote", "Good Luck!")) |
Union型を使うには型指定時に「|」で型を区切る必要があります。この例だとnumberかstringの型をどちらでも受け取れる様にしました。
3つの場合は、このようになります。
1 |
function combine(arg1:number | string | boolean, arg2:number | string) {} |
また、型指定しただけでは、渡された引数がnumber型かstring型かをTypeScriptが判断することができないので、typeof演算子で型チェックをする必要があります。
Literal型
Literal型は、型付けにnumberやstringなどを指定するのではなく、「値そのものを指定する」型です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function combine( arg1:number | string, arg2:number | string, asType: "as-string" | "as-number", // Literal型 ) { if ((typeof arg1 === "number" && typeof arg2 === "number") && asType == "as-number") { return arg1 + arg2; } return `Hello, ${arg1}, ${arg2}` } console.log(combine(10, 20, "as-number")); console.log(combine("selfnote", "Good Luck!", "as-string")) // console.log(combine("selfnote", "Good Luck!", "as-string!!!")) // error |
この例では、「type: “as-string” | “as-number”」をLiteral型として定義しました。as-stringとas-numberは任意の値です。
型エイリアス / カスタム型
型にエイリアスをつけることが可能です。
エイリアスを定義する場合は、「type」キーワードを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
type NumOrStr = number | string; type AsType = "as-string" | "as-number" function combine( arg1: NumOrStr, arg2: NumOrStr, asType: AsType, ) { if ((typeof arg1 === "number" && typeof arg2 === "number") && asType == "as-number") { return arg1 + arg2; } return `Hello, ${arg1}, ${arg2}` } |
先ほどよりかなりスッキリしたと思います。
型エイリアスは、Object型に対しても実装可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
type Book = { id: number, title: string, description: string } function bookInfo(book: Book) { for (let b in book) { console.log(b) } } const b1 = { id: 1, title: 'Harry Potter', description: 'Magic World Story' } console.log(b1) |
戻り値の型とvoid型
function型には戻り値の型があります。
これまでの戻り値の型は、TypeScriptが型推論してくれていました。

自分で明示的に型を指定することもできますが、TypeScriptが型推論してくれる場合は、無理に書く必要はありません。
1 2 3 4 |
// このようにかけるが、無理に戻り値の型を書かなくて良い function sum(num1:number, num2:number): number { return num1 + num2; } |
TypeScriptには、void型も持っています。void型は、関数が何も返さないことを明示的に指定します。

function型
TypeScriptには、関数であることを示すfunction型があります。
1 2 3 4 5 6 |
function sum(num1:number, num2:number): number { return num1 + num2; } let doSum: Function; // function型 doSum = sum; |
より正確に型を指定する場合は、以下のようにします。
1 2 3 4 |
// a, bは任意の値 // 2つの引数を受け取ってnumber型を返すことを示しており、このような構造の // functionしか代入できない let doSum: (a: number, b: number) => number; |
コールバックにも応用できます。
1 2 3 4 5 6 7 8 9 |
let doSum: (a: number, b: number) => number; doSum = sum; function sumCall(num1: number, num2: number, sum: (a: number, b: number) => number) { return sum(num1, num2); } const answer = sumCall(10, 20, doSum); console.log({answer}); |
sumCallのsumがコールバックです。ここには、明示的にどのようなfunction型を受け取るのか指定しています。
Unknown型 / Any型
Unknown型は、最終的にどのような型になるかわからないということを意味します。
一方、Any型は全ての型(string, number, functionなど)を受け入れます。
1 2 3 4 5 6 7 8 9 10 |
let userInput: unknown; let adminInput: any; let inputResult: string; // string型にunknown型入れたらエラー inputResult = userInput; // string型にany型入れてもエラーにならない inputResult = adminInput; |
any型はTypeScriptが型チェックをしないため、どのような型に代入してもエラーになりません。一方、unkown型はエラーになります。
エラーを回避したい場合は、型チェックを行う必要があります。
1 2 3 4 |
if (typeof userInput === 'string') { // 型チェックを行うことでunkown型を代入できる inputResult = userInput; } |
どのような型を指定すれば良いかわからない場合、any型よりunknown型を使う方が安全です。上記のように型チェックをする必要があるためです。
never型
never型は関数の戻り値の型として指定できます。
そして、これは「値を絶対に返さない」ことを明示的に示す役割を持っています。
例外を発生させる時など、プログラムがクラッシュするような場面で使用します。
1 2 3 4 5 6 |
function generateError(message: string, code: number): never { throw { message: message, errorCode: code } } generateError('Error happens!', 500); |
index型
index型は、オブジェクトを作成するときにそのプロパティを柔軟に定義するために使用します。
例えば、クラスのプロパティに対して、値チェック(バリデーションチェック)をしたいとします。
プロパティには、emailやuserなどがあり、それぞれに正しい値が設定しているかどうかを確認したいところですが、クラスにどのようなプロパティが設定されているかは分からない、といった状況でindex型は役に立ちます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// 最終的にエラーメッセージを格納する interface ErrorContainer { // index型は[]で定義する // propは任意の名前。何でも良い // index型は、stringかnumber型しか指定できない // prop: string -> stringと解釈される値を入力する // : string -> 最終的にプロパティに格納される型をstringとする // -> プロパティに意味する名前は知らなくてもstring型を受け取りstring型を格納する // また[]で囲っているので、受け取るパラメータは複数の可能性あり [prop: string]: string // 事前に名前がわかっているプロパティがあれば、定義できる // この場合は、idを持つクラスしか指定できない // またindex型を定義している場合は、その型に指定されている型しか // 指定することができない。ここでは、stringしか指定できない(number型は不可) id: string } |
index型は、こんな感じです。ちょっとわかりずらいかもしれませんが、実際に使ってみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
interface ErrorContainer { [prop: string]: string } const errBag: ErrorContainer = { // プロパティ名はstringに変換できるものなら指定OK // ok email: 'Invalid Email Address', // ok -> 数字も文字列として認識されるが指定はできる 1: "Invalid Email Address", username: 'Invalid UserName' } |
上記のようにindex型として定義したinterfaceをオブジェクトの型として指定すればOKです。
おわりに
本記事では、TypeScriptで使用する型について一通り学習しました。
種類がたくさんあるので、使いこなすことが難しそうですね^^;
練習あるのみだと思うので、実際にプログラムを書きながら学んでいきましょう!
それでは、また!
最近のコメント