4

-(Edited)This question does not apply to only Numbers, but about all types in general. I am using something like:

exampleFunction1(a,b){
 if(
 Object.prototype.toString.call(a) === "[object Number]" &&
 Object.prototype.toString.call(b) === "[object Number]"
 ){
 return a+b;
 }else{
 console.log('%cType Error : exampleFunction1(<Number>)','color:#00FF66;')
 }
}
exampleFunction2(type,length,format) {
 if(
 Object.prototype.toString.call(type) === "[object String]" &&
 Object.prototype.toString.call(length) === "[object Number]" &&
 (Object.prototype.toString.call(format) === "[object String]" || Object.prototype.toString.call(format) === "[object Undefined]" )
 ){
 }else{
 console.log("%cType Error : exampleFunction2(<String>,<Number>,<String>)","color:#00FF66;")
 }
 }

in almost all of my functions to strict check its input type before starting to write my actual code. And its mostly on functions that i'll share amongst my team and on my own library which other people will try to use. Is this considered as a good practice or it's unnecessary ?

5
  • 1
    It's far better to use facebook's flow or microsoft's typescript. Commented May 26, 2020 at 0:43
  • @marco-a the problem of typescript is that it does not check during run time and it breaks some of the es6 syntax, which makes it more time consuming to fix it. Commented May 26, 2020 at 0:45
  • typescript is compiled to javascript. all checks will be done during run time; though they will be implicit and hidden away Commented May 26, 2020 at 1:08
  • @richytong You sure ? According to this post's answer stackoverflow.com/a/44078574/10822847 typescript does not check type during run time. Commented May 26, 2020 at 1:12
  • okay, you got me. thanks for showing me that Commented May 26, 2020 at 1:15

3 Answers 3

1

You won't find one right answer, but you can find strong opinions. My opinion is: it varies. Here are some typechecks from my library

const isDefined = x => x !== undefined && x !== null
const isUndefined = x => x === undefined
const isNull = x => x === null
const isIterable = x => isDefined(x) && isDefined(x[Symbol.iterator])
const isAsyncIterable = x => isDefined(x) && isDefined(x[Symbol.asyncIterator])
const isReadable = x => x && typeof x.read === 'function'
const isWritable = x => x && typeof x.write === 'function'
const isFunction = x => typeof x === 'function'
const isArray = Array.isArray
const numberTypedArrays = new Set([
 'Uint8ClampedArray',
 'Uint8Array', 'Int8Array',
 'Uint16Array', 'Int16Array',
 'Uint32Array', 'Int32Array',
 'Float32Array', 'Float64Array',
])
const isNumberTypedArray = x => x && x.constructor && (
 numberTypedArrays.has(x.constructor.name)
)
const bigIntTypedArrays = new Set([
 'BigUint64Array', 'BigInt64Array',
])
const isBigIntTypedArray = x => x && x.constructor && (
 bigIntTypedArrays.has(x.constructor.name)
)
const isNumber = x => typeof x === 'number'
const isBigInt = x => typeof x === 'bigint'
const isString = x => typeof x === 'string'
const isPromise = x => x && typeof x.then === 'function'
const is = fn => x => x && x.constructor === fn
const isObject = is(Object) // checks directly for Object, isObject([]) === false

If you're looking for a quick way to just check the type given the constructor function, I recommend copy and pasting is and using it so

const is = fn => x => x && x.constructor === fn
exampleFunction1(a,b){
 if(is(Number)(a) && is(Number)(b)){
 return a+b;
 }else{
 console.log('%cType Error : exampleFunction1(<Number>)','color:#00FF66;')
 }
}

it's less to type.

answered May 26, 2020 at 1:03
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for sharing your code. Just a question: wouldn't it be much more easier to define Object.prototype.toString.call(<nameHere>) === "[object <typeHere>]" repeatedly rather than having different logic for each type ?
That actually work very well given that is(Object), is(Array), is(Float32Array) etc works just fine. Is there any type this method won't work on ?
It unfortunately does not work for TypedArray which is hidden from the global namespace. I wanted to do an easy type check for Uint8Array, Int8Array, ..., Float64Array as a group, so that's how I arrived at isNumberTypedArray. I also ran into a bunch of one off cases like isDefined where I want to conveniently check for undefined and null. So i guess that's where all the variation came from for me.
also when you just want to see if something has a certain method, like isReadable just checks for the function read. this is duck typing
For the isDefined part. If you entered nothing , is(<someType>)(input) returns "undefined" won't that be enough to check ?
0

You should use isNaN method to check is number or not as

addNumbers(a,b){
 if(
 !isNaN(a) &&
 !isNaN(b)
 ){
 return a+b;
 }else{
 console.log('%cType Error : findUniqueInArray(<Array>)','color:#00FF66;')
 }
}
answered May 26, 2020 at 0:52

3 Comments

isNaN() performs soft type check, so for example isNaN(true) is false.
Number.IsNaN if you want check for input type
@AluanHaddad Number.isNaN() on the other hand returns true just for the true NaN value. There's no magic behind it.
0

Relying on toString() doesn't seem like the safest choice, as any object can implement its own toString().

I'd go with Number.isFinite():

if (Number.isFinite(a) && Number.isFinite(b)) {

If you just want to check the type, there's a typeof operator:

typeof 1 // "number"
typeof 'a' // "string"
typeof {} // "object"

As for the toString(), libraries often implement their own toString() to help you debug. Here's how it's done with classes:

class Foo {
 toString() {
 return 'I am mr. Foo';
 }
}
const bar = new Foo();
bar.toString() // "I am mr. Foo"
answered May 26, 2020 at 0:52

10 Comments

This question is not only about numbers, but also for other types. Also can you give an example of "as any object can implement its own toString()."?
Updated my answer to explain.
typeof is unreliable because typeof Object and typeof Array returns the same result
Yup, it's not good for arrays. There's no one liner for all the types. If you wanna be type safe, use TypeScript, as suggested.
Object.prototype.toString.call(obj) never calls obj.toString so that is not an issue.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.