thai-address-search
v0.3.0
Published
Offline Thai address search and autocomplete. Zero runtime dependencies, TypeScript-first.
Maintainers
Readme
thai-address-search
ค้นหาที่อยู่ไทยและทำ autocomplete แบบ offline บน browser หรือ Node.js — TypeScript-first, zero runtime dependencies, ไม่ต้องมี API server
Offline Thai address search and autocomplete for browsers and Node.js — TypeScript-first, zero runtime dependencies, and no API server.
ข้อมูล 77 จังหวัด · 928 อำเภอ/เขต · 7,436 ตำบล/แขวง ฝังมากับแพ็กเกจ และโหลด index แบบ lazy เมื่อค้นหาครั้งแรก
Install
pnpm add thai-address-search
# หรือ npm install thai-address-searchQuick start
import { searchAddress } from 'thai-address-search';
const results = searchAddress('สุเทพ เชียงใหม่');
console.log(results[0]);
// { subdistrict: 'สุเทพ', district: 'เมืองเชียงใหม่',
// province: 'เชียงใหม่', zipcode: '50200', score: 100, ... }ค้นได้ทั้งชื่อไทย/อังกฤษ, รหัสไปรษณีย์, คำติดกัน, คำนำหน้าเขตการปกครอง, ชื่อย่อ และคำพิมพ์ผิดที่พบบ่อย:
searchAddress('สุเทพเชียงใหม่');
searchAddress('ต.สุเทพ อ.เมืองเชียงใหม่ จ.เชียงใหม่');
searchAddress('สนกำแพง');
searchAddress('กทม');
searchAddress('Suthep');คำนำหน้าไม่ได้เป็นเพียงข้อความที่ถูกตัดทิ้ง แต่ใช้จำกัดระดับการค้นหาด้วย เช่น แขวง/ต. จะค้น field ตำบล และ เขต/อ. จะค้น field อำเภอ ช่วยแยกชื่อซ้ำได้แม่นขึ้น นอกจากนี้ชื่อเต็มอย่าง เชียงใหม่ และ chiang mai จะให้ความสำคัญกับจังหวัดก่อนตำบลชื่อเดียวกัน
Next.js / React
ฟังก์ชันทั้งหมด synchronous และใช้ใน Client Component ได้โดยตรง:
'use client';
import { useState } from 'react';
import { searchAddress, type AddressResult } from 'thai-address-search';
export function AddressAutocomplete() {
const [query, setQuery] = useState('');
const results: AddressResult[] = searchAddress(query, { limit: 8 });
return (
<div>
<input
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder="ตำบล อำเภอ จังหวัด หรือรหัสไปรษณีย์"
/>
<ul>
{results.map((address) => (
<li key={address.subdistrictCode}>
{address.subdistrict}, {address.district}, {address.province} {address.zipcode}
</li>
))}
</ul>
</div>
);
}สำหรับ input จริง แนะนำ debounce 80–150 ms เพื่อให้การ render ลื่น แม้ตัว search จะ synchronous และมี LRU cache อยู่แล้ว
Vue
<script setup lang="ts">
import { computed, ref } from 'vue';
import { searchAddress } from 'thai-address-search';
const query = ref('');
const results = computed(() => searchAddress(query.value, { limit: 8 }));
</script>
<template>
<input v-model="query" placeholder="ค้นหาที่อยู่" />
<div v-for="item in results" :key="item.subdistrictCode">
{{ item.subdistrict }}, {{ item.district }}, {{ item.province }} {{ item.zipcode }}
</div>
</template>Node.js
ESM:
import { searchByZipcode } from 'thai-address-search';
console.log(searchByZipcode('50200'));CommonJS:
const { searchByZipcode } = require('thai-address-search');
console.log(searchByZipcode('50200'));API
searchAddress(query, options?)
คืน AddressResult[] เรียงคะแนนจากมากไปน้อย ค่า query ว่าง, null หรือ undefined คืน [] โดยไม่ throw
interface SearchOptions {
limit?: number; // default 10
fuzzy?: boolean; // default true
maxDistance?: number; // auto: ≤3 chars=0, 4–6=1, >6=2
minScore?: number; // default 0
lang?: 'th' | 'en' | 'auto'; // default auto
}searchByZipcode(zipcode)
คืนทุกตำบล/แขวงที่ใช้รหัสไปรษณีย์ 5 หลักนั้น
getProvinces()
คืนจังหวัดทั้งหมด 77 รายการ หากต้องการเฉพาะรายชื่อจังหวัดและ bundle ที่เล็กกว่า ใช้ subpath:
import { getProvinces } from 'thai-address-search/provinces';getDistricts(province)
รับจังหวัดเป็นรหัส, ชื่อไทย, ชื่ออังกฤษ หรือ alias เช่น getDistricts('50'), getDistricts('เชียงใหม่')
getSubdistricts(province, district)
รับจังหวัดและอำเภอเป็นรหัสหรือชื่อ แล้วคืนตำบล/แขวงทั้งหมดในอำเภอนั้น
createSearcher(options?)
สร้าง instance ที่มีค่าเริ่มต้นและ LRU cache แยกกัน:
const searcher = createSearcher({ limit: 5, fuzzy: false });
searcher.search('บางรัก');
searcher.clearCache();Result type
interface AddressResult {
subdistrict: string;
district: string;
province: string;
zipcode: string;
subdistrictEn: string;
districtEn: string;
provinceEn: string;
subdistrictCode: string;
districtCode: string;
provinceCode: string;
score: number; // 0–100
}กรุงเทพมหานครใช้คำว่า “แขวง/เขต” ในทางราชการ แต่ field ยังชื่อ subdistrict/district เหมือนจังหวัดอื่นเพื่อให้ API สม่ำเสมอ
Why this library?
| | thai-address-search | thai-address-database | | --- | --- | --- | | TypeScript types | Built in | Limited/legacy | | ESM + CommonJS | Yes | Legacy-oriented | | Runtime dependencies | 0 | Includes dependencies | | Thai-aware fuzzy search | Yes | No | | Concatenated queries | Yes | No | | Framework lock-in | None | None |
ไลบรารีนี้แยก search logic ออกจาก UI จึงใช้กับ React, Vue, Svelte, Node หรือ JavaScript ปกติได้
Data and updating
ข้อมูลมาจาก thailand-geography-data/thailand-geography-json ภายใต้ MIT License ดู attribution ฉบับเต็มใน DATA_LICENSE
raw snapshot ถูกเก็บใน data/raw/ เพื่อให้ build แบบ offline และทำซ้ำได้ เมื่อต้องการอัปเดต:
- แทนที่ JSON ทั้งสามไฟล์และแก้
data/raw/SOURCE_COMMIT - รัน
pnpm run build:dataซึ่งจะตรวจ schema, จำนวน, parent references, ชื่อ และ postcode - รัน
pnpm test && pnpm run build && pnpm run size
Development
pnpm install
pnpm run build:data
pnpm run lint
pnpm test
pnpm run build
pnpm run sizePull requests ควรมี test สำหรับ behavior ที่เพิ่มหรือแก้ และใช้ Conventional Commits เช่น feat:, fix:, docs: หรือ chore: ห้ามแก้ src/data/packed.ts ด้วยมือ
License
Library code: MIT · Dataset: MIT with attribution
