In Defense of Simple Lodash Functions

In Defense of Simple Lodash Functions

"Hey, dumb question," the new guy said to me, "Why would you use a library for 'isString'? It's not really more readable".
"I'm not sure what you mean," I replied. I hadn't even looked away from my screen yet.
"It seems like a very easy thing to check. I can write a function for it in ... less time than we've been talking. Here, let me slack one to you!"

A few moments later this appears on slack:

function isString(maybeString: unknown): maybeString is string {
    return typeof maybeString === 'string';
}

// Seems to work okay here!
const alpha = 'Hello World';
console.log(`isString: ${String(isString(alpha))}`)

Can that function fail?

"Can that function fail?" I asked him, over the cube wall.
"I mean I don't see how," he said. I could hear some uncertainty in his voice.
"Okay, let me send you back some code..."

Great. How can I check for string literals and string objects?

I'm so glad you asked. Here's a function that will work for most cases but it may not foolproof:

function betterIsString(maybe: unknown): maybe is String {
    // this base case is still easy
    if (typeof maybe === 'string') return true;

    // okay so it might be a string object? "typeof maybe" isn't 
    // super helpful on its own, because so many things report "object"

    // no 'toString' method, can't use 'in' operator on null
    return maybe != null             
        // can't use 'in' for a number or boolean either but they could be objects
        && typeof maybe == 'object'
        // okay its got a toString method!
        && 'toString' in maybe
        // 'toString' exists but returns string literals on string
        // objects, not useful for type checks. Object prototype method
        // gives checkable output. Lodash handles more such edge cases.
        && Object.prototype.toString.call(maybe) === '[object String]';
}

// YEP, this works!
console.log(`betterIsString: ${String(betterIsString(beta))}`);

Good luck remembering all that any time you need to verify data from 3rd party code is a string. Potentially a good reason for an ESLint rule banning "new String()".

And that's why I still sometimes use a library like lodash even for simple checks like "is this value a string".

If you never type check any code but your own and you've eliminated object usage then yes, using a library for _.isString() is overkill. But if not, it's safe than roll-your-own.