While investigating https://github.com/chartjs/chartjs-plugin-zoom/issues/928, I found that `isNonPrimitive` will throw TypeError on a Moment.js object after it's passed through Chart.js's options proxy, because the object has its `Symbol.toPrimitive`, `toString`, and `valueOf` all set to null.
(See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion for background reading.)
Since isNumber appears to be a low-level function that can take any arbitrary input, it seems worth letting it handle this case.
return result;
}
+/**
+ * Verifies that attempting to coerce n to string or number won't throw a TypeError.
+ */
+function isNonPrimitive(n: unknown) {
+ return typeof n === 'symbol' || (typeof n === 'object' && n !== null && !(Symbol.toPrimitive in n || 'toString' in n || 'valueOf' in n));
+}
+
export function isNumber(n: unknown): n is number {
- return !isNaN(parseFloat(n as string)) && isFinite(n as number);
+ return !isNonPrimitive(n) && !isNaN(parseFloat(n as string)) && isFinite(n as number);
}
export function almostWhole(x: number, epsilon: number) {
expect(math.isNumber(NaN)).toBe(false);
expect(math.isNumber(undefined)).toBe(false);
expect(math.isNumber('cbc')).toBe(false);
+ expect(math.isNumber(Symbol())).toBe(false);
+ expect(math.isNumber(Object.create(null))).toBe(false);
});
it('should compute shortest distance between angles', function() {