よく使う便利なTypeScriptの型システムをわかりやすくまとめてみた
インデックス型クエリ keyof ◯◯Type
keyof
を使って特定の型からその型が持つプロパティのキー名の集合(ユニオン型)を作成することができます。
下記の例では、ProfileType
型があり、この型はname、age、hobby
という3つのプロパティを持っています。ここでkeyof ProfileType
を使用すると、この型のプロパティキーのユニオンである"name" | "age" | "hobby"
を取得できます。
type ProfileType = {
name: string;
age: number;
hobby: string;
};
const profile: ProfileType = {
name: "Taro",
age: 30,
hobby: "Photography",
};
const key: keyof ProfileType = "hobby";
ブラケット記法 []
変数を使ってオブジェクトのプロパティに動的にアクセスすることができます。
先ほどのconst key: keyof ProfileType = "hobby";
の記述がなくてもprofile[key]
は使用できますが、keyの型を適切に定義することでTypeScriptの型安全性を活用することができます。
console.log(profile[key]); // "Photography"
インデックス署名 [key: 型]
通常、オブジェクトのプロパティはコード上で静的に定義されますが、動的なキーを持つオブジェクトの場合、それらのキーと値の型を事前に指定できないことがあります。インデックス署名を使用すると、動的なプロパティのキーと値の型を事前に定義でき、これによりコードの型安全性が向上します。
// ①
interface User {
id: number;
name: string;
email: string;
}
interface UserDictionary {
[userId: number]: User;
}
const users: UserDictionary = {
1: { id: 1, name: "Mike", email: "john@example.com" },
2: { id: 2, name: "Alice", email: "jane@example.com" },
};
console.log(users[1].name); // "Mike"
// ②
interface AppConfig {
[key: string]: string | number | boolean;
}
const config: AppConfig = {
theme: "dark",
version: 1.0,
notificationsEnabled: true,
};
console.log(config.theme); // "dark"
typeof 演算子
基本的なデータ型を調べることができます。
nullは、オブジェクトとして表示されるので注意してください。
// 数値
console.log(typeof 1); // "number"
// 文字列
console.log(typeof 'こんにちは'); // "string"
// ブール値
console.log(typeof true); // "boolean"
// オブジェクト
console.log(typeof {name: 'Alice'}); // "object"
// 関数
function myFunction() {}
console.log(typeof myFunction); // "function"
// undefined
let notDefined;
console.log(typeof notDefined); // "undefined"
// null(注: JavaScriptの歴史的な理由で "object" と表示される)
console.log(typeof null); // "object"
// シンボル(ES6以降)
console.log(typeof Symbol('id')); // "symbol"
型述語 is
特定の関数やメソッドが呼び出された後に引数や返り値が特定の型であることを保証するために使われます。
下記の例では、isNumber
は、任意の入力value
を受け取り、その型がnumber
であるかどうかをチェックしています。戻り値の型述語value is number
は、この関数がtrue
を返す場合にvalue
が number
型であることをTypeScriptの型システムに示しています。
const values: any[] = [10, "hello", true, 42];
const isNumber = (value: any): value is number => typeof value === 'number';
values.forEach(value => {
if (isNumber(value)) {
console.log(`${value} is a number, and its double is ${value * 2}`);
} else {
console.log(`${value} is not a number`);
}
});
// 10 is a number, and its double is 20
// hello is not a number
// true is not a number
// 42 is a number, and its double is 84
型アサーション as
as
を使うことで、型チェッカーの推論に関わらず、任意の型を強制的に割り当てることができます。
interface Data {
id: number | string;
}
const data: Data = { id: '123' };
// idプロパティが数値かもしれないが、この場合は文字列であると断定
const idString = data.id as string;
console.log(idString); // 文字列として扱われるので'123'
is keyof typeofの例
下記の例では、skills[skillKey]
の箇所でブラケット記法 []
も使用しています。
type Skill = {
technology: string;
yearsOfExperience: number;
};
type UserProfile = {
name: string;
age: number;
profession: string;
skills: {
skill1: Skill;
skill2: Skill;
skill3: Skill;
};
};
const userProfile: UserProfile = {
name: "Mike",
age: 30,
profession: "Software Engineer",
skills: {
skill1: { technology: "JavaScript", yearsOfExperience: 5 },
skill2: { technology: "TypeScript", yearsOfExperience: 3 },
skill3: { technology: "React", yearsOfExperience: 2 }
}
};
const technologies = [];
for (let i = 1; i <= 3; i++) {
// skillを指定するためのキーを生成
const skillKey = `skill${i}` as keyof typeof userProfile.skills;
// skillKeyに格納されているキー("skill1")を使用して
// userProfile.skills オブジェクトから対応するスキルオブジェクト
const skill = userProfile.skills[skillKey];
// スキルが存在する場合のみ配列に追加する
if (skill) {
// 1回目のループの場合skill.technologyはskill1.technology
technologies.push(skill.technology);
}
}
// technologiesは['JavaScript', 'TypeScript', 'React']になります
型エイリアス
型に名前を付けることができます。
type StringOrNumber = string | number;
const printId = (id: StringOrNumber) => {
console.log(id);
}
ユニオン型 string | number
複数の型をパイプ(|)で結ぶ書き方です。
const printValue = (value: string | number) => {
console.log(value);
}
printValue(123); // 数値を引数として受け入れます
printValue("Hello, World!"); // 文字列を引数として受け入れます
型キャスト Number(○○)
あるデータ型の値を別のデータ型に変換します。
//数値への変換 文字列"123"を数値123に変換
Number("123");
//文字列への変換 数値123を文字列"123"に変換
String(123);
// ブール値への変換 数値1をブール値trueに変換
Boolean(1)
終わりに
何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉
Discussion