import parse from '@pim.sk/utils/parse.mjs'
Converts string representations of primitives to their native JS types. Handles null, undefined, true, false, NaN and numbers. Non-string inputs pass through unchanged.
parse( "null" ) // → null
parse( "undefined" ) // → undefined
parse( "true" ) // → true
parse( "false" ) // → false
parse( "NaN" ) // → NaN
parse( "42" ) // → 42
parse( "3.14" ) // → 3.14
parse( 42 ) // → 42 (number passes through)
parse( true ) // → true (boolean passes through)
parse( "null" ) // → null
parse( "true" ) // → true
parse( "42" ) // → 42
parse( 42 ) // → 42
Converts numeric strings to numbers. Supports SK format (comma as decimal). Preserves strings that look like dates, phone numbers or GPS coordinates.
parse( "1 234" ) // → 1234 space as thousands separator
parse( "1,5" ) // → 1.5 SK decimal comma
// preserved as strings:
parse( "2024-01-15" ) // → "2024-01-15" SQL date (2 dashes)
parse( "15.01.2024" ) // → "15.01.2024" SK date (2 dots)
parse( "48.1234,17.5678" ) // → "48.1234,..." GPS (2+ dots)
parse( "v1.2.3" ) // → "v1.2.3" contains letter
// phone — preserved:
parse( "+421888444333" ) // → "+421888444333" leading + caught by regex
parse( "00421999555444" ) // → "00421999555444" roundtrip: 421...≠ 004...
parse( "0903555444" ) // → "0903555444" roundtrip: 903...≠ 090...
// PSC (postal code) — ⚠ use ignore= for PSC fields in objects:
parse( "075 01" ) // → "07501" space removed, leading 0 keeps string
parse( "125 52" ) // → 12552 ⚠ no leading 0 → converted to number
parse( "22512" ) // → 22512 ⚠ converted to number
parse( "1 234" ) // → 1234
parse( "1,5" ) // → 1.5
parse( "+421888444333" ) // → "+421888444333" (leading +)
parse( "00421999555444" ) // → "00421999555444" (leading 0, roundtrip protected)
parse( "0903555444" ) // → "0903555444" (leading 0)
parse( "075 01" ) // → "07501" ⚠ space removed, stays string
parse( "125 52" ) // → 12552 ⚠ converted to number
parse( "22512" ) // → 22512 ⚠ converted to number
// → use ignore="psc" when parsing objects with PSC fields
Arrays are parsed recursively — every item is converted to its native type.
parse( ["1", "true", "null", "3,14", "2024-01-15", "hello"] )
// → [ 1, true, null, 3.14, "2024-01-15", "hello" ]
parse( ["1", "true", "null", "3,14", "2024-01-15", "hello"] )
// → [ 1, true, null, 3.14, "2024-01-15", "hello" ]
Objects are parsed recursively — every value is converted to its native type. Useful for normalizing data from forms or API responses where all values arrive as strings.
const raw = {
id: "12",
active: "true",
score: "9,5",
created: "2024-01-15",
label: "hello",
empty: "null",
}
parse( raw )
// → {
// id: 12,
// active: true,
// score: 9.5,
// created: "2024-01-15",
// label: "hello",
// empty: null,
// }
parse({
id: "12",
active: "true",
score: "9,5",
created: "2024-01-15",
label: "hello",
empty: "null",
})
Recursion works at any depth. Arrays of objects and objects with sub-objects are fully traversed — every string value anywhere in the structure is converted.
// array of objects:
parse([
{ id: "1", active: "true", score: "9,5" },
{ id: "2", active: "false", score: "7" },
])
// → [
// { id: 1, active: true, score: 9.5 },
// { id: 2, active: false, score: 7 },
// ]
// nested object:
parse({
count: "3",
user: {
id: "42",
active: "true",
address: {
zip: "075 01",
city: "Trebisov",
}
}
})
// → {
// count: 3,
// user: {
// id: 42, active: true,
// address: { zip: "07501", city: "Trebisov" }
// }
// }
// array of objects
parse([
{ id: "1", active: "true", score: "9,5" },
{ id: "2", active: "false", score: "7" },
])
// nested object
parse({
count: "3",
user: { id: "42", active: "true",
address: { zip: "075 01", city: "Trebisov" }
}
})
Second argument is a comma-separated list of keys to skip. Ignored fields are left unchanged — their original string value is preserved.
// without ignore:
parse({ id: "42", code: "007", count: "3" })
// → { id: 42, code: "007", count: 3 }
// ↑ "007" stays string — leading zero protected by isSafeNumber()
// with ignore — "id" kept as string:
parse({ id: "42", code: "007", count: "3" }, "id")
// → { id: "42", code: "007", count: 3 }
// multiple ignored keys:
parse({ id: "42", code: "007", count: "3" }, "id,code")
// → { id: "42", code: "007", count: 3 }
parse({ id: "42", code: "007", count: "3" })
// → { id: 42, code: "007", count: 3 }
// ↑ leading zero preserved — roundtrip "007" → 7 → "7" ≠ "007"
parse({ id: "42", code: "007", count: "3" }, "id,code")
// → { id: "42", code: "007", count: 3 }
Third argument is a comma-separated list of keys that must be converted to boolean. String values are matched via regex /^true$|^1$|^yes$|^on$/i — only exact matches (case-insensitive) produce true, everything else produces false. Non-string values (number, bool, null…) go through boolean() cast.
// without booleans option — "1"/"0" become numbers:
parse({ active: "1", visible: "0" })
// → { active: 1, visible: 0 }
// with booleans — string matched via /^true$|^1$|^yes$|^on$/i:
parse({ active: "1", visible: "0" }, "", "active,visible") // → true / false
parse({ active: "true", visible: "yes" }, "", "active,visible") // → true / true
parse({ active: "on", visible: "ON" }, "", "active,visible") // → true / true
parse({ active: "TRUE", visible: "off" }, "", "active,visible") // → true / false
// non-string values go through boolean() cast:
parse({ active: 1, visible: 0 }, "", "active,visible") // → true / false
parse({ active: true, visible: null }, "", "active,visible") // → true / false
// "1"/"0" → numbers without booleans param:
parse({ active: "1", visible: "0", score: "9" })
// → { active: 1, visible: 0, score: 9 }
// strings matched by /^true$|^1$|^yes$|^on$/i:
parse({ a: "1", b: "true", c: "yes", d: "on",
e: "0", f: "false", g: "off", h: "no" }, "", "a,b,c,d,e,f,g,h")
// → { a: true, b: true, c: true, d: true,
// e: false, f: false, g: false, h: false }
// non-string via boolean() cast:
parse({ active: 1, visible: 0, flag: null }, "", "active,visible,flag")
// → { active: true, visible: false, flag: false }