住所をまるごと貼るだけ

tw-fuzzy-zipcode

項目に分かれていない台湾の住所から郵便番号を引き、中華郵政の規則に沿って英文住所にも変換します。台/臺、全角、漢数字の表記ゆれを理解し、県市や行政区が抜けていても検索可能。すべてクライアント側で完結し、サーバーも WASM も SQLite も不要です。

IDEA

住所は貼り付けられたままの形で

フォームの住所はきれいに分かれているとは限りません。利用者が貼り付けた生の文字列、OCR の結果、旧システムから引き継いだ単一のテキスト項目——どれも一続きの文字列です。tw-fuzzy-zipcode はそれをそのまま受け取り、県市・郷鎮市区・道路名に分ける前処理を求めません。moskytw/zipcodetw の照合アルゴリズムを JavaScript に移植したもので、実行時の依存パッケージはありません。

FUZZY MATCHING

どんな書き方でも読み取る

まず台/臺、全角、よくある漢数字の表記を正規化し、住所を県市・行政区・道路の段・巷弄・番地の断片に分けて段階的に照合します。情報が足りれば番地ルールで 6 桁を、足りなければ使える 3 桁を返し、曖昧なときは推測せず空文字を返します。

臺北市信義區市府路1號

110204

完全な住所は番地ルールで照合し 6 桁を返します。

台北市秀山街

100005

「台」は「臺」に正規化され、道路名だけでも引けます。

松山區

105

行政区だけなら、使える 3 桁を返します。

松江路100號

104091

道路名が全国で一意なら、抜けた県市と行政区を補います。

UNIQUE ROAD

書かれていない部分を補う

県市や行政区が省略されていても、残りの表記が全国で 1 本の道路にしか一致しなければ、抜けた部分を補ってから 6 桁まで照合を続けます。複数の道路に一致する場合(どこにでもある中正路など)はそのままにし、推測はしません。

入力

松江路100號

自動補完

臺北市中山區松江路100號

104091

SPEED

1 回の検索は 2 マイクロ秒未満

ブラウザ用のインデックスは、並べ替えたデータを項目ごとに 1 本の文字列へ平坦化し、Int32Array のオフセットで二分探索します。メモリは約 4 分の 1 に、それでも毎秒約 50 万回の検索を維持します。

1.7–2.0 µs

1 回の検索

34 ms

ブラウザでのインデックス読み込み

0.80 MB

Brotli 転送サイズ(gzip 約 1.21 MB)

5.3 MB

読み込み後のメモリ(ブラウザ)

データは中華郵政 2026 年 6 月の 3+3 郵便番号で、番地ルール 79,845 件と漸進住所 162,470 件を含みます。Python の参照実装との 90,950 件の差分テストで差異ゼロ。計測環境は Apple M3 Pro です。

基隆愛三路郵局第5號信箱

200900

P.O. Box 5, Keelung Ai 3rd Road, Keelung City 200900

P.O. BOX

私書箱にも対応

「〇〇郵便局第 N 号信箱」は番地ではなく、郵便番号は局名から直接対照して求めます。実際に私書箱を開設している 899 局を収録。元データには 6 桁が割り当てられていても未開設の局が 314 件あり、これらは常に空文字を返します——番号は届きそうに見えて、実際には届かないからです。

ENGLISH ADDRESS

英文住所への変換も

translate() は中華郵政の書式に従って語順を反転し、郵便番号を補って、そのまま封筒に印刷できる英文住所を返します。名称はすべて公式の中英対照によるもので、ピンインの推測はしません。同梱の目録での実測では 99.99% の住所が完全に変換できます。

臺北市中正區忠孝東路一段1巷1弄1號1樓

1F., No. 1, Aly. 1, Ln. 1, Sec. 1, Zhongxiao E. Rd., Zhongzheng Dist., Taipei City 100009, Taiwan (R.O.C.)

階・番・弄・巷・段はそれぞれ公式の略記に対応し、郵便番号も自動で調べて挿入します。

政大郵局第12號信箱

P.O. Box 12, National Chengchi University, Taipei City 116979, Taiwan (R.O.C.)

私書箱の英文局名も公式データによるもので、項目は私書箱番号と局名に変わります。

臺北市信義區四維三路2號

english: ''

四維三路は高雄市苓雅区の道路で、信義区には存在しません。名称が変換できることと住所が実在することは別——照合の結果、届かない英文住所を返すくらいなら空文字を返します。

OPEN SOURCE

MIT ライセンスのオープンソース、自由に使える

公開しているものがそのままソースで、ビルド手順はなくブラウザから直接読み込めます。Node とブラウザ両方のエントリに TypeScript の型定義を同梱しているため、@types の追加インストールは不要です。データは番地インデックス・私書箱表・中英対照の 3 つの独立した辞書に分かれており、必要なものだけ読み込めます。

郵便番号、中英対照、郵便局私書箱のデータはいずれも中華郵政によるもので、「3+3 郵遞區號公開授權聲明」および政府資料開放授權條款に従って利用しています。照合アルゴリズムは moskytw/zipcodetw からの移植です。

USAGE

使い方

実行時の依存はなく、公開しているものがそのままソースです。Node では import してすぐ検索でき、ブラウザには fs がないため loadZipcode() でパッケージ同梱のデータファイルを読み込みます。型定義も同梱しており、@types の追加は不要です。

TERMINAL

$ npm install tw-fuzzy-zipcode

NODE.JS

import { find, lookup, translate } from 'tw-fuzzy-zipcode' find('臺北市信義區市府路1號')// '110204'find('松江路100號')// '104091',路名全臺唯一,縣市與行政區可以省略lookup('臺北市')// { zipcode: '1', source: 'gradual', resolution: 'prefix' }translate('臺北市信義區市府路1號').english// 'No. 1, Shifu Rd., Xinyi Dist., Taipei City 110204, Taiwan (R.O.C.)'

BROWSER

import { loadZipcode } from 'tw-fuzzy-zipcode/browser' // 瀏覽器沒有 fs,改用 loadZipcode() 載入隨套件發布的資料檔const zip = await loadZipcode({  gradualUrl: '/data/gradual.tsv',  preciseUrl: '/data/precise.tsv',  mailboxUrl: '/data/mailbox.tsv',}) zip.find('臺北市信義區市府路1號')// '110204'

主な API

find(address)

そのまま使える 3 桁または 6 桁の郵便番号を返します。確定できないときは空文字を返し、無効な 4/5 桁の中間接頭辞は返しません。

lookup(address)

照合の段階を表示したいときに使います。{ zipcode, source, resolution } を返し、見つからなければ null です。

findAddress() / findMailbox()

番地のみ、または私書箱のみを検索するサブ関数。データがどちらか一方に限られる場合に使えます。

translate(address)

{ english, parts, untranslated, complete } を返します。郵便番号は自動で調べて挿入され、{ zipcode } で指定することもできます。

loadZipcode({ gradualUrl, preciseUrl, mailboxUrl })

ブラウザでデータファイルを読み込み、上記と同名のメソッドを持つ Zipcode を作ります。3 つの辞書は独立しており、必要なものだけ読み込めます。

loadTranslator({ roadUrl, districtUrl })

ブラウザ用の中英対照。verify と mailbox をつなぐと道路名の照合と私書箱の英訳が有効になります。

lookup() の戻り値

source

precise · gradual · mailbox

郵便番号の由来:番地ルール、漸進住所インデックス、私書箱対照表のいずれか。

resolution

six-digit · three-digit · prefix

解決できた粒度:6 桁、3 桁、または郵便番号として成立しない県市レベルの接頭辞。