"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.