3
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?

【TypeScript】JIS X 0208 の文字種チェックを Yup で実装する(encoding-japanese使用)

Last updated at Posted at 2025-10-09

1. はじめに

経緯

現在参画中のプロジェクトでシステムの保守開発をしています。
共通で使用できる文字種のバリエーションチェックの用のカスタムメソッドを新たに実装することになりました。
試行錯誤して作成したので、備忘録として残します。

JIS X 0208 とは

JIS X 0208 は、日本の文字コード規格のひとつです。
全角文字を中心に定義されており、漢字(第1水準・第2水準)、ひらがな・カタカナ、記号(句読点や括弧など)、キリル文字(ロシア文字)、ギリシャ文字、罫線素片などを含む計6879字の文字集合です。
半角文字(半角カナ・半角英数字)は含まれません。

JIS X 0208 で許容される文字種についてはこちらをご覧ください。

2.実装

1.encoding-japaneseライブラリのインストール

encoding-japanese を使います。

npm または yarn でインストールします。

# npm
npm install encoding-japanese

# yarn
yarn add encoding-japanese

2.ファイルの作成

カスタムメソッドを定義するファイル(例:CustomYupMethods.tsx)を作成します。
Yup(JavaScript / TypeScript 向けのバリデーションライブラリ)に独自のメソッドを追加するイメージです。
今回は NEC拡張 / IBM拡張 (Windows固有などの追加の機種依存文字 例:①②㈱髙 )も範囲外とします。

CustomYupMethods.tsx
import * as Yup from "yup";
import * as Encoding from 'encoding-japanese';

// ========================================== 
// 関数定義 
// ==========================================
export const isJISX0208 = (value: string | null | undefined): boolean => {
  if (!value) return true;

  try {
    const unicodeArray = Encoding.stringToCode(value);
    const sjisArray = Encoding.convert(unicodeArray, {
      to: 'SJIS',
      from: 'UNICODE',
    }) as number[];

    // '?' に置き換わった(変換不能)ならNG
    if (Encoding.codeToString(sjisArray).includes("?")) return false;

    // 各2バイトを確認
    for (let i = 0; i < sjisArray.length; i++) {
      const b1 = sjisArray[i];
      const b2 = sjisArray[++i];
      if (!b2) return false;

      const code = (b1 << 8) | b2;

      // CP932のNEC拡張・IBM拡張を除外
      const isJisX0208 =
        (code >= 0x8140 && code <= 0x9FFC) ||
        (code >= 0xE040 && code <= 0xEA9E);

      const isNecExt = (code >= 0x8740 && code <= 0x879E); // NEC拡張
      const isIbmExt =
        (code >= 0xED40 && code <= 0xEEFC) ||
        (code >= 0xFA40 && code <= 0xFC4B); // IBM拡張

      if (!isJisX0208 || isNecExt || isIbmExt) {
        return false;
      }
    }

    return true;
  } catch {
    return false;
  }
};


// ========================================== 
// カスタムメソッドの型定義 
// ==========================================
declare module 'yup' {
  interface StringSchema {
    isJISX0208(message?: string): this;
  }
}

// ========================================== 
// カスタムメソッドの実装 
// ==========================================
Yup.addMethod(Yup.string, 'isJISX0208', function(message?: string) {
  return this.test('isJISX0208', message || 'JIS X 0208の文字で入力してください', function(value) {
    const { path, createError } = this;
    if (!value) return true;
    if (!isJISX0208(value)) {
      return createError({ path, message });
    }
    return true;
  });
});


JIS X 0208 の範囲外の文字を使うと、Shift_JIS 変換時に '?' に置き換わることがある。

3.使用例

import * as yup from 'yup';
import '@/utils/customYupMethods'; // カスタムメソッドを定義したファイルのパス

const validationSchema = yup
  .string()
  .isJISX0208();

呼び出し側でメッセージを上書きすることも可能です。

const validationSchema = yup
  .string()
  .isJISX0208("使用できない文字が含まれています");

3.まとめ

本記事がどなたかのお役に立てれば幸いです。
内容に誤りや改善点などございましたら、ぜひご指摘ください。

3
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
3
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?