Well, it was a kind of a joke intended for the folks whose brain saw the comment the same way I did. I got the result by applying the footnote to the object, as half-suggested by syntax of the parent:
The core problem here is that you don't actually want to check if something is an object, but whether it matches the Human type. The correct way to do that is to define a type guard [0], for example:
function isHuman(input: any): input is Human {
return (
Boolean(input) &&
Object.prototype.hasOwnProperty.call(input, "name") &&
Object.prototype.hasOwnProperty.call(input, "age")
);
}
There are libraries which can automate this for you which is the route I would recommend if you need to do this often. As you can see, the code to cover all edge cases such as `Object.create(null)` etc is not trivial.
That's fairly subjective and I can see arguments for both sides, in the above example I've gone with the approach the Typescript documentation itself gives which uses any. Given the parameter is only used as an input, using any and unknown are interchangeable and there is no difference in this specific case.
While I see where you're coming from, semantic formulation like this is highly subjective. All the same the problem statement could be "Given any kind of input, tell me whether it's a Human or not".
This approach is "correct" only when you're interacting with an API you have no control over whatsoever because specifying all this and maintaining it is really error prone.
All this boilerplate is not a proof. It remains an assertion. And so in most cases you might as well just add a "type"/"kind" property to your object (or create a class).
Personally I really enjoy Typanion [0] since it's very similar to Yup [1] which I previously had extensive experience with. You can find more alternatives and a lengthy discussion about the whole problem space and its history in [2].
I very, very much disagree with the type of suggestions here. Probably because I don't know TS but here it comes anyways...
You don't need a library or check that it isn't an array or anything like that. What you actually want to check is what it _is_.
You absolutely don't care whether that object is an array or a function or what have you. What you care about in that piece of code is that it satisfies what you want to do with it.
In the context of the article you can do an ad-hoc check on the fields that you require in that context.
Aside:
There are places where you want to have a kind of rigidity around the shape of your objects, including homogeneous collections. The JIT might reward you with optimizations in certain cases. But that is optimization, so you are supposed to measure first and only then apply them or have a very clear picture of how your runtime behavior will be.
Probably best to just lift one off of a major library like Lodash, they're well tested and efficient (no need to actually use the library, do include the LICENSE somewhere though):
Why not use the library? With tree shaking and/or direct imports you will ensure the same bundle size as if you just copied the file, and you don't have to worry about licenses etc. In fact, since other dependencies might depend on lodash you can deduplicate the import and actually save on bundle size.
You'll also get notified of any security issues in your lodash imports if your CI pipeline is setup for doing that kind of thing.
Mostly if you look at it out of the context of a single function - a lot of projects end up taking a huge number of dependencies, with a lot of overlapping functionality, because you used one function from this one, another function from that one… I’m fine with using libraries when they actually do heavy lifting that’s core to an application, but a single two line function requiring including hundreds of unrelated irrelevant ones? That will impact the coding style of your team and does have security downsides, like needing to trust the library authors and potentially breaking your build because they changed their APIs or deleted a package or whatever. Copying a 2 line function has very clear boundaries to what it can and can’t do, and doesn’t hide the internals of what you’re doing behind the mystique of “an external dependency”.
If you want to avoid a library then you can do `typeof x === "object" && !Array.isArray(x) && x !== null`. Not ideal, but you can of course turn it into a utility function.
`entry` is a valid Human here, but fails your check. Actually, just creating a new class that implements the Human interface will cause a similar problem, since the constructor will be the class instead of Object. You don't even really want to exclude arrays here:
You're absolutely right. Should have stated that I meant a plain object (key-value-pair). But either didn't want to focus on this topic for that post because it would have been just a bit too much to talk about :D
I really like this package, because it not only uses the method you mentioned for checking types, but is written in TS, so you get the type checking feedback.