TypeScript勉強用メモ
サバイバルTypeScriptを見ていく。
基本的な型は以下。
boolean: 真偽値。
number: 数値。
string: 文字列。
bigint: 大きな整数。
symbol: 一意の値を示す。
undefined: 値が定義されていない状態を示す。
null: 値が存在しない状態を示す。
JSの型と同じ。
TS独自の型。
特殊な型
any: 何でも代入できる型。型が不明な場合に使用する。その値に対する操作の制限がなく、型の安全性は弱まる。
unknown: any型と似て、何でも代入できる型。その値に対する操作は制限され、型の安全性が保たれる。
void: 値が存在しないことを示す。関数が何も返さない場合に使用する。
never: 決して何も返さないことを示す。エラーを投げる関数や無限ループの関数の戻り値として使用する。
unknown
はany
と異なり、代入はできるが操作はできない。
操作とは例えば、四則演算など値を用いた何かしらの操作を指す。
→型が不明であるため、「1 + x」が文字列の結合か数値の加算か判別できないからだと思う。
void
はその他の言語と同じように正常な場合かつ戻り値がない場合に利用。
never
は例外を返すなど、そもそも戻り値を返すことがない場合に利用。
型エイリアス
type StringOrNumber = string | number;
let value: StringOrNumber;
value = "hello"; // string型が代入可能
value = 123; // number型も代入可能
StringOrNumber
型を新たに定義。
数値か文字列のみ代入可能となる。
構造的部分型
type Summary = { name: string };
type Detail = { name: string; age: number };
const johnDetail: Detail = { name: "John", age: 28 };
const summary: Summary = johnDetail; // 代入できる。構造的部分型として互換があるため
const johnSummary: Summary = { name: "John" };
const detail: Detail = johnSummary; // 代入できない。構造的部分型として互換がない(ageを含まないため)
Detail
はSummary
を含むため互換性がある。
一方で、Summary
はage
を含まないため、Detail
と互換性がない。
よって、Detail
型の変数にSummary
型の値を代入しようとした場合、エラーが出る。
※定義されていないものがある分には問題ないが、定義されているものがない場合は問題となるらしい。
配列の型注釈
let numbers: number[];
let strings: Array<string>;
タプル型
let tuple: [string, number];
tuple = ["hello", 10]; // 代入できる
tuple = [10, "hello"]; // 順序が正しくないため、代入できない
tuple = ["hello", 10, "world"]; // 要素が多すぎるため代入できない
いわゆる配列に複数の型が混じっているもの。
型定義の順番に代入する必要がある。
オブジェクトリテラル
let obj: { name: string; age: number };
readonly
を付けた場合は代入禁止。
※定義はできる
let obj: { readonly name: string; age: number };
obj = { name: "John", age: 20 };
obj.name = "Tom"; // ダメ
オプションプロパティ
?
を付けたプロパティは省略することが可能。
let obj: { name: string; age?: number };
obj = { name: "John" }; // `age`プロパティがなくてもエラーにならない
インデックス型
型定義にあっているものは追加できるため、可変長になる。
let obj: { [key: string]: number };
obj = { key1: 1, key2: 2 };
console.log(obj["key1"]);
console.log(obj["key2"]);
列挙型 (Enum)
enum Color {
Red,
Green,
Blue,
}
値を代入することもできる。
enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}
利用する場合は以下
const myColor: Color = Color.Red;
ユニオン型
複数の型のうち、どれかをとる値。
let value: boolean | number;
value = true; // 代入できる
value = 100; // 代入できる
インターセクション型
type Octopus = { swims: boolean };
type Cat = { nightVision: boolean };
type Octocat = Octopus & Cat;
const octocat: Octocat = { swims: true, nightVision: true };
console.log(octocat);
全てを持つ新たな型が作られる。
型の絞り込み
let value: string | number;
// 50%の確率でstring型またはnumber型の値を代入する
value = Math.random() < 0.5 ? "Hello" : 100;
if (typeof value === "string") {
// この節ではvalueはstring型として扱われる
console.log(value.toUpperCase());
} else {
// この節ではvalueはnumber型として扱われる
console.log(value * 3);
}
つまり、条件分岐後は型が確定した状態となるため、おかしな使い方をしているとエラーになる。
関数
const greet = (name: string): string => {
return `Hello ${name}`;
};
console.log(greet("John"));
または
function greet(name: string): string {
return `Hello ${name}`;
}
console.log(greet("John"));
型宣言に関してはアロー関数でも通常の関数でも変わらない。
分割代入
通常の変数宣言と感覚としてはほぼ同じ。
const printCoord = ({ x, y }: { x: number; y: number }) => {
console.log(`Coordinate is (${x}, ${y})`);
};
printCoord({ x: 10, y: 20 });
型ガード関数
特定の型であることを判定し、型を絞り込む。
is
は戻り値がBoolean
のときに使用可能。
value is string
とした場合、戻り値がtrue
の場合はその型がstring
であると解釈される。
※JSに変換したときに型が正しいかは別の話。
function isString(value: any): value is string {
return typeof value === "string";
}
function printLength(value: any) {
if (isString(value)) {
// この節ではvalueはstring型として扱われる
console.log(value.length);
}
}
printLength("hello");
type importとtype export
export type MyObject = {
name: string;
age: number;
};
import type { MyObject } from "./types";
// ^^^^型インポート
const obj: MyObject = {
name: "TypeScript",
age: 3,
};
型ファイルを作成しておき、必要な型のみインポートすることも可能。
typeof
は変数名から型を取得。
keyof
はobject
型のすべてのキーを文字列リテラルのユニオン型として取得。
ユーティリティ型
Required
はオプションプロパティを必須にする。
Partial
は型のすべてのプロパティをオプションにする。
上記は対になる。
Readonly
は型のすべてのプロパティをreadonlyにする。
Record
はオブジェクトのすべてのプロパティ値を特定の型に設定する。
Pick
はオブジェクトから特定のプロパティだけを拾い出す。
Omit
はオブジェクトから特定のプロパティを省いた型を作る。
この二つは対となる。
Exclude
はユニオン型から特定の型を除外する。
Extract
はふたつのユニオン型の共通の部分を抽出する。
NonNullable
はnullまたはundefinedを含む型からいずれも除外する。
ReturnType
は関数の戻り値の型を取得する。
Awaited
はPromiseの戻り値の型を取得する。