On This Page
Coercion Utilities
The Coercion utilities turn loose input — attribute strings, query params, form values, JSON — into the type you actually want. Each returns the target type or null when the input has no clean representation, so a failed coercion is a value you can guard with ??, never an Invalid Date, NaN, or "[object Object]" that poisons code downstream.
const page = toNumber(params.get('page')) ?? 1;const when = toDate(input.value) ?? new Date();Each helper is also exported as coerceBoolean, coerceNumber, coerceInteger, coerceDate, and coerceString for callers who think in coercion terms.
Every helper accepts an onInvalid setting. It defaults to 'null' (the failed coercion returns null, composing with ??). Pass { onInvalid: 'passthrough' } to return the original value instead, so a schema or validator can flag the bad input rather than see an erasing null — and the TypeScript return widens to include the input type (number | string for toNumber(str, { onInvalid: 'passthrough' })).
Functions
toBoolean
function toBoolean(value, { truthy, falsy, loose = false, onInvalid = 'null' } = {})Coerces a value to a boolean, or null when it recognizes no boolean reading. Booleans pass through, numbers read by zero-ness, and strings match a generous set case-insensitively: true, t, yes, y, on, enabled read as true, and false, f, no, n, off, disabled, null, undefined, nan read as false, alongside numeric strings by their value. Anything else returns null.
Parameters
| Name | Type | Description |
|---|---|---|
| value | unknown | The value to coerce |
| settings | object | Optional configuration |
Options
| Name | Type | Default | Description |
|---|---|---|---|
| truthy | string | string[] | — | Extra tokens to treat as true for this call, winning over the config vocabulary |
| falsy | string | string[] | — | Extra tokens to treat as false for this call, winning over the config vocabulary and a truthy match |
| loose | boolean | false | Coerce unrecognized input via native truthiness instead of returning null |
| onInvalid | ‘null’ | ‘passthrough’ | ‘null’ | How an unrecognized value resolves (loose takes precedence when both are set) |
Returns
true, false, or null if unrecognized. Never null under loose.
Example
import { toBoolean } from '@semantic-ui/utils';
console.log(toBoolean('yes')); // trueconsole.log(toBoolean('off')); // falseconsole.log(toBoolean('false')); // false (not the native Boolean('false') === true)console.log(toBoolean('1')); // true
// unrecognized input is null, so it composes with ??console.log(toBoolean('banana')); // nullconsole.log(toBoolean('banana') ?? false); // false
// loose falls back to native truthiness, never nullconsole.log(toBoolean('banana', { loose: true })); // true
// extend the falsy set without losing the defaultsconsole.log(toBoolean('nope', { falsy: ['nope'] })); // falsetoBoolean.config
toBoolean.config holds the recognized vocabulary (truthy, falsy) and the defaults for loose and onInvalid. Edit it once at app boot and every call inherits it, so a locale or domain adds its own spellings in one place instead of passing truthy/falsy on every call. Per-call settings still win over it.
import { toBoolean } from '@semantic-ui/utils';
// teach it another language, oncetoBoolean.config.truthy.push('oui', 'sÃ');toBoolean.config.falsy.push('non', 'nein');
console.log(toBoolean('oui')); // trueconsole.log(toBoolean('non')); // false
// flip a default for every calltoBoolean.config.onInvalid = 'passthrough';console.log(toBoolean('banana')); // 'banana'toNumber
function toNumber(value, { onInvalid = 'null' } = {})Coerces a value to a finite number, or null when it can’t be converted. Numeric strings parse via Number (so hex, scientific, and surrounding whitespace are fine), booleans read as 1 and 0, and NaN, Infinity, blanks, unit-tagged strings, arrays, and objects return null. It never hands back NaN or Infinity.
Parameters
| Name | Type | Description |
|---|---|---|
| value | unknown | The value to coerce |
| settings | object | Optional configuration (onInvalid, see above) |
Returns
The finite number, or null if unconvertible.
Example
import { toNumber } from '@semantic-ui/utils';
console.log(toNumber('3.14')); // 3.14console.log(toNumber(' 42 ')); // 42console.log(toNumber('5px')); // nullconsole.log(toNumber('1e999')); // null (overflow to Infinity)console.log(toNumber(true)); // 1
console.log(toNumber('abc') ?? 0); // 0toInteger
function toInteger(value, { onInvalid = 'null' } = {})Coerces a value to an integer by truncating toward zero, or null when it’s unconvertible or non-finite. Equivalent to toNumber followed by a truncation, so Infinity joins the null bucket. Under { onInvalid: 'passthrough' } it returns the original value, never a truncated NaN.
Parameters
| Name | Type | Description |
|---|---|---|
| value | unknown | The value to coerce |
| settings | object | Optional configuration (onInvalid, see above) |
Returns
The truncated integer, or null if unconvertible.
Example
import { toInteger } from '@semantic-ui/utils';
console.log(toInteger('3.9')); // 3console.log(toInteger('-3.9')); // -3console.log(toInteger(42.7)); // 42console.log(toInteger(Infinity)); // nulltoDate
function toDate(value, { onInvalid = 'null', epoch = 'milliseconds' } = {})Coerces a value to a Date, or null when it can’t be parsed — never an Invalid Date. Accepts a Date, a number read as epoch milliseconds, or an ISO-8601 string. Ambiguous or locale-dependent spellings return null rather than a guessed date: bare years, slash and text dates, and day overflow all reject, so '01/15/2024' and '2024-02-30' never become a wrong Date. A zoneless datetime resolves in the ambient timezone (the user’s zone on the client) and is returned as a UTC instant, the same as native new Date on an <input type="datetime-local"> value. A date-only string is read as UTC, and a timestamp passed as a string is rejected, so pass a number for epoch ms.
Parameters
| Name | Type | Description |
|---|---|---|
| value | unknown | The value to coerce |
| settings | object | Optional configuration |
Options
| Name | Type | Default | Description |
|---|---|---|---|
| epoch | ‘milliseconds’ | ‘seconds’ | ‘milliseconds’ | How a number reads. Pass 'seconds' for unix-second timestamps (a JWT exp), where the millisecond reading would produce a valid but wrong 1970 date |
| onInvalid | ‘null’ | ‘passthrough’ | ‘null’ | How a failed coercion resolves (see above) |
Returns
The Date, or null if unparseable.
Example
import { toDate } from '@semantic-ui/utils';
console.log(toDate('2024-01-01')); // Date for 2024-01-01console.log(toDate(1700000000000)); // Date from epoch msconsole.log(toDate(payload.exp, { epoch: 'seconds' })); // Date from a unix-second JWT expconsole.log(toDate('01/15/2024')); // null (ambiguous format)console.log(toDate('banana')); // null (never an Invalid Date)
const when = toDate(userInput) ?? new Date();toString
function toString(value, { loose = false, onInvalid = 'null' } = {})Coerces a value to a string, or null when there is no faithful string form. Strings pass through and a finite number, a boolean, or a bigint goes through String(). Objects, arrays, functions, symbols, non-finite numbers, and nullish return null, so a String field never silently stores "[object Object]" or "NaN". Under loose, objects and arrays render with JSON for display output, still returning null on unserializable input rather than throwing.
Parameters
| Name | Type | Description |
|---|---|---|
| value | unknown | The value to coerce |
| settings | object | Optional configuration |
Options
| Name | Type | Default | Description |
|---|---|---|---|
| loose | boolean | false | Render objects and arrays with JSON instead of returning null |
| onInvalid | ‘null’ | ‘passthrough’ | ‘null’ | How a value with no faithful string form resolves |
Returns
The string, or null if there is no faithful string form.
The loose output is a display string, not a round-trippable serialization — JSON drops undefined and functions and rewrites Date and NaN, so it should not be fed back through toDate or toNumber.
Example
import { toString } from '@semantic-ui/utils';
console.log(toString(42)); // '42'console.log(toString(true)); // 'true'console.log(toString({ a: 1 })); // nullconsole.log(toString({ a: 1 }, { loose: true })); // '{"a":1}'console.log(toString([1, 2], { loose: true })); // '[1,2]'