# es-hangul for Hangul Search and Josa Handling

> es-hangul is a TypeScript library for Korean text processing in JavaScript applications. Its documented APIs cover initial-consonant matching and particle selection, with separate ESM and CommonJS package exports.

**toss/es-hangul** — A modern JavaScript library for handling Hangul characters.

- Repository: https://github.com/toss/es-hangul
- Website: https://es-hangul.slash.page/
- Stars: 1,887 · Forks: 146
- Language: TypeScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/toss-es-hangul

## The Hangul-specific problems es-hangul solves

es-hangul addresses JavaScript applications that need common Korean text operations without implementing Hangul-specific rules directly. The README presents two concrete cases. The first is search by initial consonants, where a stored word such as `라면` is reduced to `ㄹㅁ` and compared with a user entry. The second is particle selection, where a word such as `사과` receives `을` or `를` according to whether it ends with a consonant or vowel.

This is a focused library rather than a general Korean-language toolkit. `package.json` identifies Hangul, Korean, text processing, initial search, particle processing, and character decomposition as its subject areas. The README, however, gives concrete examples only for `getChoseong` and `josa`. The project is aimed at developers building interfaces where Korean search behavior or grammatically selected particles matter, especially teams working in JavaScript or TypeScript.

The distinction matters. A general string library can manipulate Unicode text, but it does not automatically tell an application which initial consonants correspond to a Korean word or which particle should follow that word. es-hangul places those rules behind named functions. This keeps search matching and sentence construction out of feature code while giving the package a clear functional boundary.

## getChoseong and josa string processing

The documented data flow for `getChoseong` is compact. The function accepts a complete word and returns its initial-consonant representation. In the README example, passing `라면` returns `ㄹㅁ`. A caller can compare that result with an input containing the same initials, which supports search when users enter only choseong. The example performs direct equality rather than approximate matching, so the library output does not decide how the surrounding application should handle partial or incorrect input.

`josa` serves a different purpose. It receives a word and a paired particle form, then selects the appropriate ending. The pair `을/를` produces `사과를`, while `이/가` produces `바나나가`. The README appends ordinary sentence text, showing how the returned particle becomes part of a larger UI or document string.

These examples define behavior at the public API level. The README does not expose internal composition tables, Unicode decomposition steps, handling of non-Hangul characters, or rules for mixed strings. Although the repository contains `src/` and TypeScript configuration, those source details are not presented in the README. Teams adopting the package must therefore verify edge cases through the public behavior they require rather than assume rules that the documentation leaves unspecified.

## Initial-consonant matching in a TypeScript search

The README does not provide a package installation command, so this tutorial starts with an already installed `es-hangul` dependency. Importing `getChoseong` and comparing its result with a user-entered choseong string creates the basic matching flow shown in the documentation.

```tsx
import { getChoseong } from 'es-hangul';

const searchWord = '라면';
const userInput = 'ㄹㅁ';
const result = getChoseong(searchWord);

if (result === userInput) {
  console.log('초성이 일치합니다.');
}
```

The library-dependent expectation is specific: `getChoseong(searchWord)` should produce `ㄹㅁ`, allowing equality with `userInput`. The Korean log message is application code, not output specified by es-hangul.

This example does not add tokenization, indexing, spelling correction, or fuzzy search. es-hangul provides the Hangul-specific transformation, while the application remains responsible for what strings it searches, how it presents matches, and whether exact equality is sufficient. A larger search service may combine the result with its own database query, but the README does not prescribe that architecture.

## Selecting Korean particles in application text

Particle selection is the clearest first use because the README documents two sentence results. Import `josa`, pass a noun and a slash-separated particle pair, then concatenate the returned particle with the rest of the sentence.

```tsx
import { josa } from 'es-hangul';

const word1 = '사과';
const sentence1 = josa(word1, '을/를') + ' 먹었습니다.';
console.log(sentence1);
```

The documented result is `'사과를 먹었습니다.'`. A second example selects the subject or topic particle for `바나나`.

```tsx
import { josa } from 'es-hangul';

const word2 = '바나나';
const sentence2 = josa(word2, '이/가') + ' 맛있습니다.';
console.log(sentence2);
```

The documented result is `'바나나가 맛있습니다.'`. This pattern may fit dynamically generated notifications, labels, or sentences, but the README does not claim native support for every Korean noun ending. It also does not document punctuation, quoted values, measurements, compound expressions, or mixed Korean and Latin text. Such cases require direct verification before they enter user-facing output.

## ESM, CommonJS, and published TypeScript files

The package supports two module-loading paths. In `package.json`, the root export has an `import` condition that points types to `./dist/index.d.mts` and JavaScript to `./dist/index.mjs`. A separate `require` condition points types to `./dist/index.d.ts` and JavaScript to `./dist/index.js`. This arrangement matters for ESM applications as well as CommonJS consumers whose bundler or runtime follows conditional package exports.

The README says the library uses ECMAScript Modules and can deliver a minimal amount of code in browser environments. `package.json` also declares `"type": "commonjs"`. Those declarations are not contradictory because the export map supplies separate files for `import` and `require`. The package metadata identifies `es-hangul` version `2.4.0`, and the published `files` field contains `dist/*`, limiting package contents to built distribution files and the metadata exposed by `./package.json`.

The repository defines a `build` script using `tsup` and a `typecheck` script using `tsc --noEmit`. It also defines package checks through `publint`, type compatibility checks through `attw`, and tests through `vitest`. These are contributor workflows, not commands an application consumer needs after installation. The README and package metadata provide no bundle-size figures or browser support matrix, so the browser claim should not be interpreted as a measured performance guarantee.

## Hangul.js, release history, and upgrade boundaries

The README credits `hangul-js` and its owner for Hangul-related contributions, but it does not compare the projects' APIs, correctness rules, bundle sizes, or performance. Based on the documented position, es-hangul offers a TypeScript-oriented package with conditional exports and separate declaration files. A direct technical comparison with `hangul-js` cannot be made from the README.

Release history lists `es-hangul@2.4.0` on 2026-07-09, following `2.3.7` and `2.3.8` from September 2025. The repository is not archived, and the last push was on 2026-08-27. These dates indicate recent development, but upgrading still requires checking `CHANGELOG.md`. The repository includes `.changeset/` and defines `changeset:version` and `changeset:publish` scripts, so consumers can use release notes as the source for assessing API changes between versions.

Version upgrades are not automatically risk-free for user-facing Korean text. A change in particle selection, decomposition, or export types could alter application output or TypeScript compatibility. Reviewing each relevant entry in `CHANGELOG.md` is more useful than assuming semantic versioning alone captures every visible string change.

## MIT licensing and the boundary of documented behavior

es-hangul uses the MIT License. The README names Viva Republica, Inc. as the copyright holder and links the repository's `LICENSE` file. The MIT License generally permits use, copying, modification, distribution, sublicensing, and sale, subject to its conditions, including retention of the copyright and license notices. Consumers with organization-specific compliance requirements should read the actual `LICENSE` file and check notices for files they distribute. This is a technical summary, not legal advice.

The principal functional boundary is equally important. The README does not document translation, pronunciation, linguistic analysis, automatic spacing, or broad normalization. It also does not define behavior for malformed particle pairs, empty strings, punctuation, non-Hangul input, or mixed-script values. es-hangul may still participate in a larger Korean text system, but it should not be treated as a complete language-processing service.

Its strongest fit is a codebase that repeatedly needs `getChoseong` or `josa` and values a small named API with TypeScript declarations. Its weakest fit is an application expecting full Korean grammar or automatic sentence generation. Verify required edge cases against the public functions, inspect `CHANGELOG.md` when upgrading, and confirm that the package's ESM or CommonJS export matches the consuming build tool.

## Conclusion

es-hangul fits applications that need common Korean string operations without implementing those rules in feature code. It is a poor fit for translation, pronunciation, morphological analysis, or broad Korean-language processing. Before adoption, verify `getChoseong` and `josa` against the Korean search terms, punctuation, mixed text, and sentence forms used by your application.

## FAQ

### What can es-hangul do with Korean text?

The README documents `getChoseong` for extracting an initial-consonant representation and `josa` for selecting between paired particles. It does not present es-hangul as a translation or full linguistic-analysis library.

### Does es-hangul support ESM and CommonJS?

Yes. The package export map points `import` consumers to `./dist/index.mjs` and `require` consumers to `./dist/index.js`, with separate type declaration files for each condition.

### What license does es-hangul use?

The project uses the MIT License and names Viva Republica, Inc. as the copyright holder. The repository's `LICENSE` file contains the complete terms.

### Can es-hangul perform fuzzy Korean search?

The README example compares the exact output of `getChoseong` with an exact user-entered string. It does not document fuzzy matching, typo correction, or search ranking.

## Sources

- [License: MIT](https://github.com/toss/es-hangul/blob/main/LICENSE)
- [Project website](https://es-hangul.slash.page/)
- [README](https://github.com/toss/es-hangul/blob/main/README.md)
- [Releases](https://github.com/toss/es-hangul/releases)
- [toss/es-hangul on GitHub](https://github.com/toss/es-hangul)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/toss-es-hangul
