8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

typescriptであるパターンに従った型定義をしたい

Posted at

typescriptの型定義であるパターン(たとえばメールアドレスや郵便番号)を型として表現したいと思ったことはないですか?
限界はあると思いますが、下記のように表現可能です。

type GMail = `${string}@gmail.com`;

const mail1: GMail = 'hogehoge@gmail.com';
const mail2: GMail = 'hogehoge@yahoo.co.jp'; // ERROR. Type '"hogehoge@yahoo.co.jp"' is not assignable to type '`${string}@gmail.com`'.

type PostCode = `${number}-${number}`;

const postCode1: PostCode = '123-1234';
const postCode2: PostCode = 'aaa-aaaa'; // ERROR. Type '"aaa-aaaa"' is not assignable to type '`${number}-${number}`'.
const postCode3: PostCode = '12345678'; // ERROR. Type '"12345678"' is not assignable to type '`${number}-${number}`'.

正規表現ほど柔軟にできませんが、個人的には十分だなと感じました。
TypeScriptすごい。。。ちなみに、正規表現を使用して型判定したい場合ユーザ定義タイプガードを使って実装するというアイデアも使いどころはありますね。

declare const postCodeSymbol: unique symbol;
type PostCode = string & { [postCodeSymbol]: never };

// 正規表現にマッチした場合、vをPostCode型として型付けする
const isPostCode = (v: string): v is PostCode => {
  return /^\d{3}-\d{4}/.test(v);
}

const postCode = "123-1234";

// PostCode型を引数に取る
const setPostCode = (postCode: PostCode) => {
  console.log(postCode);
}

// isPostCodeによってPostCode型であると認識される
if (isPostCode(postCode)) {
  // ここではエラーでない
  setPostCode(postCode);
} else {
  // PostCode型として認識されてないのでエラー
  setPostCode(postCode); // ERROR. Argument of type 'string' is not assignable to parameter of type 'PostCode'.
}
8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?