📌

TypeScript入門 【組み込みユーティリティ&型アサーションと型ガード】

2021/10/26に公開

今回はTypeScriptの組み込みユーティリティと、型ガードについて説明していきます。

どちらも現場では良く見るコードなので、一緒に学んでいきましょう。

組み込みユーティリティ


まずはジャンル毎に組み込みユーティリティをいくつか紹介します。

オブジェクト型

よく使われるオブジェクト型に使う組み込みユーティリティを次の3つです。

  • Partial …… T のプロパティをすべて省略可能にする
  • Required …… T のプロパティをすべて必須にする
  • Readonly …… T のプロパティをすべて読み取り専用にする

それぞれ以下のように使います。


type nameType = {
  firstName?: string;
  lastName: string;
};
//全て省略可能
const name0: Partial<nameType> = {};
//全て省略不可
const name1: Required<nameType> = {
  firstName: "shiya",
  lastName: "hinohara"
};
//型は元のまま 値の変更が不可になる
const name2: Readonly<nameType> = {
  lastName: "hinohara"
};

また、次の3つも結構使われます。

  • Pick …… T から K が指定するキーのプロパティだけを抽出する
  • Omit …… T から K が指定するキーのプロパティを省く
  • Record …… K の要素をキーとしプロパティ値の型を T としたオブジェクトの型を作成する

それぞれ実際に使うと次のようになります。


type userType = {
  firstName?: string;
  lastName: string;
  type: string;
};
// 元の方からいくつかを取り出せる
const nameProp: Pick<userType, "firstName" | "lastName"> = {
  firstName: "shinya",
  lastName: "hinohara"
};
// Omitでも表現できる
const nameProp2: Omit<userType, "type"> = {
  firstName: "shinya",
  lastName: "hinohara"
};
// number型がプロパティとなり、userTypeをもつ型となります。
type userList = Record<number, userType>;
const users = { 0: { firstName: "taro", lastName: "sato", type: "free" } };

列挙型

次に列挙型に使う組み込みユーティリティをいくつか紹介します。

  • Extract …… T から U の要素だけを抽出する
  • Exclude …… T から U の要素を省く
  • NonNullable …… T から null と undefined を省く

実際に使うと次のようになります。


type hoby = "reading" | "traveling" | null | undefined;
const myHoby: Extract<hoby, "reading"> = "reading";
const myHoby2: Exclude<hoby, "reading"> = "traveling";
const hobies: NonNullable<hoby> = "reading";

後、次の4つも覚えておいて損はないです。

  • Uppercase …… T の各要素の文字列をすべて大文字にする
  • Lowercase …… T の各要素の文字列をすべて小文字にする
  • Capitalize …… T の各要素の文字列の頭を大文字にする
  • Uncapitalize …… T の各要素の文字列の頭を小文字にする


type countries1 = "japan" | "USA" | "chiNese";
// type countries2 = "USA" | "JAPAN" | "CHINESE"
type countries2 = Uppercase<countries1>;
// type countries3 = "japan" | "usa" | "chinese"
type countries3 = Lowercase<countries1>;
// type countries4 = "USA" | "Japan" | "ChiNese"
type countries4 = Capitalize<countries1>;
// type countries5 = "japan" | "chiNese" | "uSA"
type countries5 = Uncapitalize<countries1>;

関数

最後に関数に使う組み込みユーティリティをいくつか紹介します。

  • Parameters …… T の引数の型を抽出し、タプル型で返す
  • ReturnType …… T の戻り値の型を返す

それぞれ実際に使うと


const plus = (num1: number, num2: number): number => {
  return num1 + num2;
};
// type plusType = [num1: number, num2: number]
type plusType = Parameters<typeof plus>;
// type plusReturn = number
type plusReturn = ReturnType<typeof plus>;

型アサーションと型ガード


次に型アサーションと型ガードについて説明します。

型アサーションはas ~と書く事で、コンパイラによる型の解釈が変える手法になります。

このasのはT as (U extends T)または(T extends U) as Uであるとき、つまりTがUのサブタイプであるかUがTのサブタイプである場合にしか使えないものなります。

実際に見ないと良く分からないと思うので、次の例を見てください。


// myCountry=stringとコンパイラに伝える
const myCountry = "japan" as string;
// TがUのサブタイプでもUがTのサブタイプでもないのでエラーになる
const test = 1 as string;

この型アサーションは一見あまり使いどころが内容に思えますが、型ガードをする時に便利です。

型ガードとは、Unknown型を使うための型を保証するチェックのことです。

これも実際に例を見て見ましょう。


const myname: unknown = "taro";
// プリミティブ型(null以外)の型ガードにはtytpeofが使える
if (typeof myname === "string") {
  console.log("hello");
}

class User {
  name: string;
  height: number;
  constructor(name: string, height: number) {
    this.name = name;
    this.height = height;
  }
}
const user1: unknown = new User("taro", 173);
// クラスの型ガードにはinstanceofが使える
if (user1 instanceof User) {
  console.log("hello2");
}

しかし、ただのオブジェクトに対して型ガードしたい時は、自前で型を絞り込むしくみを作ってあげる必要があります。

それは『ユーザー定義の型ガード』と呼ばれる方法で、次の通りです。


type User = { username: string; address: { zipcode: string; town: string } };
const isUser = (arg: unknown): arg is User => {
  const u = arg as User;
  return (
    typeof u?.username === "string" &&
    typeof u?.address?.zipcode === "string" &&
    typeof u?.address?.town === "string"
  );
};
const u: unknown = JSON.parse(
  '{ "username": "patty", "address": { "zipcode": "111", "town": "Maple Town" } }'
);
if (isUser(u)) {
  console.log("heloo");
}

関数 isUser()の戻り値の型定義がarg is Userという見慣れない記述になっていますが、これは型述語という表現で、この関数がtrueを返す場合に引数 argの型がUserであることがコンパイラに伝えることができます。

以上。

最後に宣伝です。

0からエンジニアになるためのノウハウをブログで発信しています。
https://hinoshin-blog.com/

また、YouTubeでの動画解説も始めました。
YouTubeのvideoIDが不正ですhttps://www.youtube.com/channel/UCqaBUPxazAcXaGSNbky1y4g

インスタの発信も細々とやっています。
https://www.instagram.com/hinoshin_enginner/

興味がある方は、ぜひリンクをクリックして確認してみてください!

おわり

Discussion