はじめに
私は普段フロントエンドエンジニアとして開発しながら働いています。
TypeScriptの基礎について備忘録的に残しておきたいと思います。
この記事の対象者
- JavaScriptの次にTypeScriptを学びたい人
- TypeScriptの型定義について学びたい人
TypeScriptとは
TypeScriptはJavaScriptを拡張した言語になります。
従来のJavaScriptでは型がany
でしたが、品質の向上が求められ、型定義を用いるTypeScriptが使われるようになりました。
主なデータ型の種類
// string型
const name: string = "Taro";
// number型
const age: number = 1;
// boolean型
const flg: boolean = true;
// arrayのstring型
const array: string[] = ["apple", "banana", "grape"];
:
の後に明示的に型を定義することを「アノテーション」と呼びます。
型推論
TypeScriptでは上記のようにアノテーションを使わなくても自動で型をつけてくれます。これを型推論といいます。
let name = "Taro"; // string型
// Bad:nameはstring型のため代入できない
name = 1;
// Good:string型のため代入できる
name = "Ken";
配列の型定義
// number型のみ許容する配列
const array1: number[] = [1, 2, 3];
// number型 or string型のみ許容する配列
const array2: (number | string)[] = [1, 2, "hoge"];
interface
オブジェクトの型定義はinterfaceを使います。
interface PROFILE {
name: string;
age?: number;
}
const person1: PROFILE = {
name: "Taro",
age: 22,
};
上記のage
のようにオブジェクト要素に後ろに「?」を付与することでプロパティを任意にすることもできます。
// 'age'要素がなくてもOK
const person2: PROFILE = {
name: "Kenji",
};
Intersection Types
複数の型を結合した型をIntersection Typesと言います。
下記だとSTAFF
が該当します。
type PROFILE = {
name: string;
age: number;
};
type JOB = {
office: string;
category: string;
};
type STAFF = PROFILE & JOB;
const personA: STAFF = {
name: "Jiro",
age: 29,
office: "Tokyo",
category: "Engineer",
};
Union Types
|(パイプ)を用いることで2つ以上の型を使うことができます。
let value: string | null = "hoge";
// Good
value = "test";
// Good
value = null;
// Bad
value = 1;
Literal Types
代入可能な値を明示的に型にすることもできます。
let fruits: "apple" | "banana" | "grape";
// Good
fruits = "apple";
// Bad
fruits = 'melon'
typepf
宣言済みの変数などから型を継承したい場合はtypeofを使います。
let message: string = "Hoge";
// string型を継承
let newMessage: typeof message = "HogeHoge";
// Bad
newMessage = 1;
keyof
オブジェクトの型からプロパティ名(キー)を型とするのがkyeofになります。
type KEYS = {
first: string;
second: string;
};
let value: keyof KEYS;
value = "first";
// Bad
value = "third";
enum
列挙型はenumを使います。
下記だとSOCCER
に0、BASEBALL
に1が割り当てられます。
enumを用いることで可読性が高まり、メンテナンスしやすくなります。
enum SPORTS {
SOCCER,
BASEBALL,
}
interface STUDENT {
name: string;
club: SPORTS;
}
const studentA: STUDENT = {
name: "Ken",
club: SPORTS.BASEBALL,
};
Generics
Genericsを用いることで使用する度に型を宣言することができます。
同じようなコードを別の型で繰り返す場合などに役立ちます。
慣習的にT
などが使われることが多いです。
interface GEN<T> {
msg: T;
}
const gen1: GEN<string> = { msg: "hoge" };
const gen2: GEN<number> = { msg: 2 };
デフォルトの型を定義すると<string>
などの宣言がなくても大丈夫です。
interface GEN<T = string> {
msg: T;
}
const gen1: GEN = { msg: "hoge" };
またextends
を併せて用いることで使用できる型を制限することができます。
interface GEN<T extends string> {
msg: T;
}
// Good
const gen1: GEN<string> = { msg: "hoge" };
// Bad
const gen2: GEN<number> = { msg: 2 };
関数で使う場合
function func<T>(value: T) {
return value;
}
func<string>("hello");
func<number>(123);
func<null>(null);
関数でextends
を使う場合
function func<T extends string>(value: T) {
return value;
}
// Good
func<string>("hello");
// Bad
func<number>(123);
interfaceと併せて使う場合
interface Props {
name: string;
}
function func<T extends Props>(value: T) {
return value;
}
func({name:'Taro'});
最後に
いかがだったでしょうか。
今回はTypeScriptの基礎についてご紹介しました。
少しでもお役に立てれば幸いです。