DEV Community

Discussion on: JavaScript Type Checking... Without TypeScript

Collapse
 
bytebodger profile image
Adam Nathaniel Davis • Edited

First, the phrase "I just made a library, inspired by this post" is always music to my ears. So kudos to you!

As for the specifics of what you've written - I like it! Now, in case anyone else is reading this comment and thinking, "Oh cool - this completely replaces what Adam did in the original post," I'd say: not quite. But that's not a knock on what you've written. Again - I like it!

The difference between your approach and mine is that yours is using the type inference supplied in the default values to ensure that any values passed in match those types. And that's hella-cool. I could absolutely see using your approach in those instances where the default values are sufficient to constrain the function parameters.

But part of my inspiration for writing my little utility class was that, in many cases, I don't find the default values to be sufficient to define what is "acceptable" input. For example, imagine a function like this:

const updateFirstName = (firstName = '') => {
  // do the updating logic here...
}

In this scenario, the function requires a string. And your approach is awesome for ensuring that the firstName value is a string. The only "problem" this leads to is that an empty string is still, technically, a string.

Now it's perfectly feasible that, in some scenarios, it might be acceptable to know that any string was passed in. Maybe the logic for your app is totally cool with the idea that, on occasion, the function might get called with an empty string for the firstName value. But usually, when I'm writing a function like this, or when I'm looking at a function that's already been written like this, it's not really acceptable to think that the firstName value might be the empty string.

You might be thinking, "Well, this is my app, and I know all the places where updateFirstName() is getting called. And I know that, on the calling end, I would never pass in an empty string for firstName." And that's... OK. It's definitely not wrong.

But one of my tenets for writing "the tightest code possible" is that you can never fully guarantee just how a function will be called. Maybe someone else will start working in your codebase and carelessly write some code that will pass an empty string in for firstName? Maybe you haven't 100% accounted for all the places where your own code is calling updateFirstName()? Whatever the scenario, I believe firmly that the proper performance of a function should never be dependent upon the idea that the function is called in the "right" way.

Because every function is, in a quite-literal sense, its own standalone program. And every program should be as fault-tolerant as possible.

So in the scenario above, using my little utility, I would code it up like this:

const updateFirstName = (firstName = '') => {
  if (!is.aPopulatedString(firstName))
    return;
  // do the updating logic here...
}

Notice that I'm not just checking to ensure that the value is a string. I'm specifically ensuring that it's a populated string, cuz there's a much greater likelihood that an empty string is "wrong" and a populated string is "acceptable".

In my utility, I have a bunch of potential checks that look for things like:

  • Is this a populated string/array/object?
  • Is this a non-negative integer?
  • Is this a GUID?

None of this as meant as any kinda criticism of what you've written. It's cool!!! I'm just pointing out where your utility would shine, and where you might still need to reach for mine.

Thank you for this utility and for the feedback!!

Collapse
 
easrng profile image
easrng

Thanks for the feedback! I made this mostly because it will make adding the checks to my code a lot easier, because I'm lazy and usually don't do any checks at all. My utility simply removes many of the checks that feel redundant, and I recognize that it is not a replacement for yours.