😎

yupにIPアドレスのバリーションを組み込む

に公開

概要

タイトルのとおり、yup に IP アドレスのバリーションを組み込む方法です。

ちなみに執筆時点での yup の最新バージョンは 1.6.1 です。

yup には IP アドレスのバリーションがない

「yup IP address validation」と検索すると、以下の Issue がヒット。

[Feature Request] validation IP address (at least IPv4) #628
https://github.com/jquense/yup/issues/628

レポジトリオーナーによると、yup 自体に IP アドレスのバリーションを加えるつもりはないとのこと。つまり、自前でカスタムバリデーションを作成します。

自前で正規表現を組むのはちょっと厳しい

IPアドレスの仕様はけっこう複雑なので、自前で正規表現を組むのは不安があります。
かつ、すべてのケースを網羅するテストを書くのも大変そうです。
というわけで、利用できるライブラリを探します。

ip-address パッケージを利用

ip-address というパッケージを利用することにしました。

https://github.com/beaugunderson/ip-address

  • IPアドレスに対するバリデーターやバージョンチェックなど、ほしい機能が揃っている
  • それなりに見やすいドキュメントが用意されている
  • スター数がそれなりに多い

などの理由で採用しました。

共通メソッドの作成しておく

ip-address パッケージでは、IPv4 と IPv6 でクラスが分かれています。共通のメソッドは無さそう…?なので、ちょっとした自作を行います。

import { Address4, Address6 } from 'ip-address';

export const IP_VERSION = {
  IPv4: 'IPv4',
  IPv6: 'IPv6',
} as const;

type IpVersion = (typeof IP_VERSION)[keyof typeof IP_VERSION];

export const isIpAddress = (value: string) => {
  return Address4.isValid(value) || Address6.isValid(value);
};

yup のカスタムバリデーションとして組み込む

先ほど作成した共通メソッドを利用して、yup のカスタムバリデーションを定義します。

import * as yup from 'yup';
import { isIpAddress } from './ipAddress';

declare module 'yup' {
  interface StringSchema {
    ipAddress(): StringSchema;
  }
}

yup.addMethod(yup.string, 'ipAddress', function () {
  return this.test({
    name: 'ipAddress',
    message: '正しいIPアドレスを入力してください',
    test: (value) => (value === undefined || value === '' ? true : isIpAddress(value)),
  });
});

export default yup;

あとは、フォームコンポーネントなどで使えばOKだと思います。
以上です!

Discussion