Open33

TypeScript勉強用メモ

YaonaYaona

TS独自の型。

特殊な型
any: 何でも代入できる型。型が不明な場合に使用する。その値に対する操作の制限がなく、型の安全性は弱まる。
unknown: any型と似て、何でも代入できる型。その値に対する操作は制限され、型の安全性が保たれる。
void: 値が存在しないことを示す。関数が何も返さない場合に使用する。
never: 決して何も返さないことを示す。エラーを投げる関数や無限ループの関数の戻り値として使用する。
YaonaYaona

unknownanyと異なり、代入はできるが操作はできない。
操作とは例えば、四則演算など値を用いた何かしらの操作を指す。
→型が不明であるため、「1 + x」が文字列の結合か数値の加算か判別できないからだと思う。

voidはその他の言語と同じように正常な場合かつ戻り値がない場合に利用。
neverは例外を返すなど、そもそも戻り値を返すことがない場合に利用。

YaonaYaona

型エイリアス

type StringOrNumber = string | number;
let value: StringOrNumber;
value = "hello"; // string型が代入可能
value = 123; // number型も代入可能
YaonaYaona

StringOrNumber型を新たに定義。
数値か文字列のみ代入可能となる。

YaonaYaona

構造的部分型

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を含まないため)
YaonaYaona

DetailSummaryを含むため互換性がある。
一方で、Summaryageを含まないため、Detailと互換性がない。

よって、Detail型の変数にSummary型の値を代入しようとした場合、エラーが出る。
※定義されていないものがある分には問題ないが、定義されているものがない場合は問題となるらしい。

YaonaYaona

配列の型注釈

let numbers: number[];
let strings: Array<string>;
YaonaYaona

読み取り専用配列

const numbers: readonly number[] = [1, 2, 3];
const strings: ReadonlyArray<string> = ["hello", "world"];
 
numbers[0] = 4; // 値を変更できない
strings.push("!"); // 要素を追加できない
YaonaYaona

JSだとconstで定義しても、配列の中身は変更できる。
変数の参照自体は変わっていないため。
TSは中身の変更も制限できる。

YaonaYaona

タプル型

let tuple: [string, number];
tuple = ["hello", 10]; // 代入できる
tuple = [10, "hello"]; // 順序が正しくないため、代入できない
tuple = ["hello", 10, "world"]; // 要素が多すぎるため代入できない
YaonaYaona

いわゆる配列に複数の型が混じっているもの。
型定義の順番に代入する必要がある。

YaonaYaona

オブジェクトリテラル

let obj: { name: string; age: number };
YaonaYaona

readonlyを付けた場合は代入禁止。
※定義はできる

let obj: { readonly name: string; age: number };
obj = { name: "John", age: 20 };
obj.name = "Tom"; // ダメ
YaonaYaona

オプションプロパティ
?を付けたプロパティは省略することが可能。

let obj: { name: string; age?: number };
obj = { name: "John" }; // `age`プロパティがなくてもエラーにならない
YaonaYaona

インデックス型
型定義にあっているものは追加できるため、可変長になる。

let obj: { [key: string]: number };
obj = { key1: 1, key2: 2 };
console.log(obj["key1"]);
console.log(obj["key2"]);
YaonaYaona

列挙型 (Enum)

enum Color {
  Red,
  Green,
  Blue,
}

値を代入することもできる。

enum Color {
  Red = "red",
  Green = "green",
  Blue = "blue",
}

利用する場合は以下

const myColor: Color = Color.Red;
YaonaYaona

ユニオン型
複数の型のうち、どれかをとる値。

let value: boolean | number;
value = true; // 代入できる
value = 100; // 代入できる
YaonaYaona

インターセクション型

type Octopus = { swims: boolean };
type Cat = { nightVision: boolean };
type Octocat = Octopus & Cat;
 
const octocat: Octocat = { swims: true, nightVision: true };
console.log(octocat);
YaonaYaona

型の絞り込み

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);
}
YaonaYaona

つまり、条件分岐後は型が確定した状態となるため、おかしな使い方をしているとエラーになる。

YaonaYaona

関数

const greet = (name: string): string => {
  return `Hello ${name}`;
};
 
console.log(greet("John"));

または

function greet(name: string): string {
  return `Hello ${name}`;
}
 
console.log(greet("John"));
YaonaYaona

型宣言に関してはアロー関数でも通常の関数でも変わらない。

YaonaYaona

分割代入
通常の変数宣言と感覚としてはほぼ同じ。

const printCoord = ({ x, y }: { x: number; y: number }) => {
  console.log(`Coordinate is (${x}, ${y})`);
};
 
printCoord({ x: 10, y: 20 });
YaonaYaona

型ガード関数
特定の型であることを判定し、型を絞り込む。

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");
YaonaYaona

type importとtype export

export type MyObject = {
  name: string;
  age: number;
};
import type { MyObject } from "./types";
//     ^^^^型インポート
 
const obj: MyObject = {
  name: "TypeScript",
  age: 3,
};
YaonaYaona

型ファイルを作成しておき、必要な型のみインポートすることも可能。

YaonaYaona

typeofは変数名から型を取得。
keyofobject型のすべてのキーを文字列リテラルのユニオン型として取得。

YaonaYaona

ユーティリティ型
Requiredはオプションプロパティを必須にする。
Partialは型のすべてのプロパティをオプションにする。
上記は対になる。

Readonlyは型のすべてのプロパティをreadonlyにする。
Recordはオブジェクトのすべてのプロパティ値を特定の型に設定する。

Pickはオブジェクトから特定のプロパティだけを拾い出す。
Omitはオブジェクトから特定のプロパティを省いた型を作る。
この二つは対となる。

Excludeはユニオン型から特定の型を除外する。
Extractはふたつのユニオン型の共通の部分を抽出する。

NonNullableはnullまたはundefinedを含む型からいずれも除外する。

ReturnTypeは関数の戻り値の型を取得する。

AwaitedはPromiseの戻り値の型を取得する。