| name | mongez-supportive-is-primitives |
| description | Documents the six primitive and numeric predicates — `isString`, `isNumeric`, `isInt`, `isFloat`, `isPrimitive`, and `isScalar` — including their semantics, edge cases, and known bugs.
TRIGGER when: code imports `isString`, `isNumeric`, `isInt`, `isFloat`, `isPrimitive`, or `isScalar` from `@mongez/supportive-is`; user asks "how do I check string / number / int / float", "detect a numeric string like '12'", "difference between isPrimitive and isScalar", or "type-narrow a string in TS"; typical import is `import { isString, isNumeric } from "@mongez/supportive-is"` (or `Is.string(x)` / `Is.numeric(x)` via the legacy default `Is` namespace).
SKIP: native `typeof v === "string"` or `Number.isInteger(v)` checks where you don't need this package — those are correct and avoid this package's known `isInt`/`isFloat` negative-number bugs; `@mongez/reinforcements` for string/number transformations (not predicates); schema validators.
|
Primitives & numbers
Six predicates for primitive-type and numeric checks. All are O(1) and run anywhere.
| Predicate | Quick rule |
|---|
isString(v) | typeof v === "string" (excludes new String(...)) |
isNumeric(v) | Number-or-numeric-string, regex-based |
isInt(v) | typeof v === "number" AND Number.isInteger(v) |
isFloat(v) | typeof v === "number" AND finite AND stringifies to /^-?\d+\.\d+$/ |
isPrimitive(v) | string | number | boolean | bigint (NOT symbol/null/undefined) |
isScalar(v) | string | number | boolean | bigint | symbol |
isString
isString("");
isString("hello");
isString(`x${1}`);
isString(new String("x"));
isString(0);
isString(null);
For TS narrowing, wrap it in a typed guard — isString itself is typed as (value: any) => boolean, not value is string:
import { isString } from "@mongez/supportive-is";
function isStr(v: unknown): v is string {
return isString(v);
}
isNumeric
Recognizes numbers AND numeric strings:
isNumeric(0);
isNumeric(-1.5);
isNumeric("12");
isNumeric("+1");
isNumeric("1.5E-3");
isNumeric("");
isNumeric("1.");
isNumeric("12abc");
isNumeric(null);
isInt & isFloat
Both require typeof value === "number":
isInt(0);
isInt(1);
isInt(-1);
isInt(1.0);
isInt(1e21);
isInt(1.5);
isInt("2");
isInt(NaN);
isInt(Infinity);
isFloat(1.5);
isFloat(0.1);
isFloat(-1.5);
isFloat(1);
isFloat(1.0);
isFloat("1.5");
isFloat(NaN);
isFloat(Infinity);
isPrimitive vs isScalar
The only difference is Symbol:
| Value | isPrimitive | isScalar |
|---|
"x" | true | true |
1, 1.5, 1n | true | true |
true, false | true | true |
Symbol("x") | false | true |
null | false | false |
undefined | false | false |
[], {}, () => {} | false | false |
isPrimitive is named for "what you can use in + / ===", which excludes Symbol. isScalar is "anything that isn't an object reference".
Notes
isPrimitive(Symbol(...)) returning false is intentional — call isScalar instead if you want symbols included.
isInt now delegates to Number.isInteger, and isFloat gates on Number.isFinite, so both correctly handle signed values and reject NaN / Infinity.