1
0

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

はじめに

2022-08-30 のような文字列を /\d\d\d\d-\d\d-\d\d/ という正規表現を満たす型として表現出来ないかで悩んでいたところ、同僚から TypeScript: Type Safe Date Strings という記事を教えてもらったので、この記事を参考に型安全な日付型を実装してみました。

日付を構成する要素を型で表現する

日付は、 , , という要素に分解できるので、まずはこれらを型で表現することを試みます。

, ,

TypeScript は Template Literal Types をサポートしており、${} で リテラルのUnion型を展開することが出来ます。

は上位2桁について(200年に限定すると) 19 | 20 、 下位2桁は 00 ~ 99 、それぞれの桁は 0-9 であるため、Template Literal Types を使い以下のように定義出来ます。

type d = 1|2|3|4|5|6|7|8|9|0;
type YYYY = `19${d}${d}` | `20${d}${d}`;

型とほぼ同様に、 型も以下のように表現できます。

type oneToNine = 1|2|3|4|5|6|7|8|9;
type MM = `0${oneToNine}` | `1${0|1|2}`;

type DD = `${0}${oneToNine}` | `${1|2}${d}` | `3${0|1}`;

Day型を作る

Date型はオチがあるので、まずは Day型を作ります。

class Day {
  static isDayString(day: string): day is DD {
    return !!day.match(/\d\d/)
  }

  private _day: DD | undefined

  constructor(day: string) {
    if (Day.isDayString(day)) {
      this._day = day
    }
  }
}

Type Guard を使い、day: stringDD 型に絞り込みますが、DD 型は Template Literal Types で展開され、 0131 までのリテラルのUnion型が定義されました。

筆者のVSCode上でも展開された状態で表現されています。

Screenshot 2022-08-31 002852.jpg

Date型を作る

ここまで来たらオチがわかったかもしれませんが、ひとまずDay型と同様にDate型を作ってみます。

export type DateYMDString = `${YYYY}-${MM}-${DD}`;

export class Date {
  static isDateYMDString(date: string): date is DateYMDString {
    return !!date.match(/\d\d\d\d-\d\d-\d\d/)
  }

  private _date: DateYMDString | undefined

  constructor(date: string) {
    if (Date.isDateYMDString(date)) {
      this._date = date
    }
  }
}

上記のコードでコンパイルなどは通ると思いますが、IDE上で入力すると、突然CPUが唸り声をあげるかもしれません。

Screenshot 2022-08-31 003945.jpg

IDE上ではDay型と同様に Template Literal Types1900-01-012099-12-31 まで、 75000近くのリテラル型が展開されました。

実用上使えるか

常識的な感覚だと、75000近くのリテラル型が展開されるのは多く感じますし、TypeScript側でも 100'000 までしかサポートされていないということです。
1900-01-012099-12-31 まで200年近くしか対応できていないのに、上限に近づいているということで、 Template Literal Types で型安全な日付型を作るのは、実用的な面でいうと厳しいと感じました。

また、別の方法などありましたら、コメントいただけると幸いです。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?