In TypeScript, use the following function which can accept any value:
const isFixed = (o: any) => {
const s = String(o)
return !isNaN(+s) && isFinite(+s) && (typeof o === 'number' || !/e/i.test(s))
}
Or if you're only checking strings:
const isFixedString = (s: string) => !isNaN(+s) && isFinite(+s) && !/e/i.test(s)
Note that the explicit String()
casting in the first function is to avoid calling the value's toString()
or valueOf()
or [Symbol.toPrimitive]()
more than once and risk checking conflicting values of auto-updating types like { n: 0, valueOf: () => n++ }
.
The casts using the unary +
operator in both definitions are specifically for the parameter types to be compatible with the global definitions in TypeScript for isNaN()
and isFinite()
, which expect a number
argument for some reason even though JavaScript can handle any type. Otherwise these casts can be removed without any change to the result.
Explanation
Just using !isNaN(mystring)
, you will check whether casting the string with Number()
will result in NaN
:
let arr = ['5', '-5', '.5', '5.', '0', '5e0', '5E0', 'Infinity', '-Infinity', '5a', 'n', '--5'];
arr.forEach(str => console.log(str, !isNaN(str)))
It should be noted that this approach also accepts scientific notation and Infinity
, which needs to be handled separately with isFinite(mystring) && !/e/i.test(mystring)
:
let arr = ['5', '-5', '.5', '5.', '0', '5e0', '5E0', 'Infinity', '-Infinity', '5a', 'n', '--5'];
arr.forEach(str => console.log(str, !isNaN(str) && isFinite(str) && !/e/i.test(str)))