News for hackers. Stuff that matters.
Re:Tricks I wish I knew when I learned TypeScript by EnderShadow8 on Tuesday October 12, 2021 @04:44AM (#28837470)
Note: don't use typeof x === 'object' to check whether something is a valid object, because it will return true for arrays as well.

Arrays are objects, so this is expected behaviour.

Re:Tricks I wish I knew when I learned TypeScript by conaclos on Tuesday October 12, 2021 @05:39AM (#28837834)
And it will return true for null as well ;)
Re:Tricks I wish I knew when I learned TypeScript by hardwaresofton on Tuesday October 12, 2021 @11:16AM (#28840764)
Re:Tricks I wish I knew when I learned TypeScript by IggleSniggle on Tuesday October 12, 2021 @05:26PM (#28845280)
Did anybody else have their brain do a weird backflip seeing `Array.isArray[0]`??

  Object.getOwnPropertyDescriptors(Array.isArray)
  /* 
  {
    '0': {
      value: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray',
      writable: true,
      enumerable: true,
      configurable: true
    },
    length: { value: 1, writable: false, enumerable: false, configurable: true },
    name: {
      value: 'isArray',
      writable: false,
      enumerable: false,
      configurable: true
    }
  }
  */
Re:Tricks I wish I knew when I learned TypeScript by panzerklein on Wednesday October 13, 2021 @03:03AM (#28849063)
How did you get that result? I only see length and name.
Re:Tricks I wish I knew when I learned TypeScript by IggleSniggle on Wednesday October 13, 2021 @07:18PM (#28858745)
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:

  Array.isArray[0] = urlString
Re:Tricks I wish I knew when I learned TypeScript by Etheryte on Tuesday October 12, 2021 @12:46PM (#28841902)
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.

[0] https://www.typescriptlang.org/docs/handbook/advanced-types....

Re:Tricks I wish I knew when I learned TypeScript by wdfx on Tuesday October 12, 2021 @01:50PM (#28842758)
Your input parameter type should be unknown, not any.
Re:Tricks I wish I knew when I learned TypeScript by Etheryte on Tuesday October 12, 2021 @01:56PM (#28842838)
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.
Re:Tricks I wish I knew when I learned TypeScript by wdfx on Tuesday October 12, 2021 @02:02PM (#28842942)
I somewhat agree, but to me the semantics using unknown makes more sense as the function is attempting to answer a question of the input object.

"What is object? I don't know. Does it meet these conditions? Yes then object is Human else not."

Re:Tricks I wish I knew when I learned TypeScript by Etheryte on Tuesday October 12, 2021 @02:45PM (#28843471)
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".
Re:Tricks I wish I knew when I learned TypeScript by mikojan on Tuesday October 12, 2021 @03:20PM (#28843896)
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).

Re:Tricks I wish I knew when I learned TypeScript by pbowyer on Tuesday October 12, 2021 @03:05PM (#28843741)
> There are libraries which can automate this for you which is the route I would recommend

Which libraries do you recommend? I've had to do this a couple of times in my current project and it's painful (and I made mistakes).

Re:Tricks I wish I knew when I learned TypeScript by Etheryte on Tuesday October 12, 2021 @06:09PM (#28845660)
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].

[0] https://github.com/arcanis/typanion

[1] https://github.com/jquense/yup

[2] https://github.com/microsoft/TypeScript/issues/3628

Re:Tricks I wish I knew when I learned TypeScript by WA on Tuesday October 12, 2021 @05:49AM (#28837893)
Note: please post a better solution.
Re:Tricks I wish I knew when I learned TypeScript by dgb23 on Tuesday October 12, 2021 @06:41AM (#28838155)
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.

Re:Tricks I wish I knew when I learned TypeScript by presentation on Tuesday October 12, 2021 @05:59AM (#28837961)
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):

https://github.com/lodash/lodash/blob/master/isObject.js

But depends on your needs, and you can also attach a typeguard to it.

Re:Tricks I wish I knew when I learned TypeScript by chucky on Tuesday October 12, 2021 @11:01AM (#28840595)
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.

Re:Tricks I wish I knew when I learned TypeScript by presentation on Thursday October 14, 2021 @11:41PM (#28873962)
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”.
Re:Tricks I wish I knew when I learned TypeScript by nicoburns on Tuesday October 12, 2021 @06:10AM (#28838021)
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.
Re:Tricks I wish I knew when I learned TypeScript by Fckd on Tuesday October 12, 2021 @08:02AM (#28838688)
x && !Array.isArray(x) && typeof x === 'object'.

its typical to start off with `var &&` to avoid operations on null & undefined values

Re:Tricks I wish I knew when I learned TypeScript by Fckd on Tuesday October 12, 2021 @08:28AM (#28838849)
For environment lacks Array.isArray method i think this works well

!!(x && x.__proto__ === [].__proto__)

Re:Tricks I wish I knew when I learned TypeScript by otrahuevada on Tuesday October 12, 2021 @07:50AM (#28838608)
a simple solution would be

> if(entry && entry.constructor === Object){}

Re:Tricks I wish I knew when I learned TypeScript by jwalton on Tuesday October 12, 2021 @08:07AM (#28838719)
This isn't a great solution:

    entry = Object.create(null);
    entry.name = "Jason";
    entry.age = 42;
    entry.constructor === Object // false - constructor is undefined.
`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:

    entry = []
    entry['name'] = "Jason";
    entry['age'] = 42;
Again, entry is a valid Human here.
Re:Tricks I wish I knew when I learned TypeScript by otrahuevada on Tuesday October 12, 2021 @08:13AM (#28838760)
I'm having some trouble finding your proposal in the thread... how would you do it?
Re:Tricks I wish I knew when I learned TypeScript by jwalton on Tuesday October 12, 2021 @10:37AM (#28840223)
:) Fair enough:

    function isHuman(obj: unknown): obj is Human {
      return !!obj && 
        typeof obj === 'object' &&
        typeof (obj as any).name === 'string' &&
        typeof (obj as any).age === 'number';
    }
This checks the shape of the object, and returns true if it's a `Human`. This will work for array or objects or classes or anything.
Re:Tricks I wish I knew when I learned TypeScript by nsonha on Tuesday October 12, 2021 @06:51AM (#28838214)
https://javascriptweblog.wordpress.com/2011/08/08/fixing-the...

tl;dr: Object.prototype.toString.call, you most likely to also want to exclude null, RegExp, Function, Date, Number, Boolean & String (not string)

Re:Tricks I wish I knew when I learned TypeScript by cstrnt on Tuesday October 12, 2021 @06:44AM (#28838174)
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
Re:Tricks I wish I knew when I learned TypeScript by threatofrain on Tuesday October 12, 2021 @06:11AM (#28838027)
How about

any => Object.prototype.toString.call(any).slice(8, -1)

Re:Tricks I wish I knew when I learned TypeScript by JoBrad on Tuesday October 12, 2021 @07:17AM (#28838361)
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.

https://github.com/sindresorhus/is

Re:Tricks I wish I knew when I learned TypeScript by nsonha on Tuesday October 12, 2021 @06:46AM (#28838187)
or even this

typeName = Object.prototype.toString.call

Re:Tricks I wish I knew when I learned TypeScript by nsonha on Tuesday October 12, 2021 @06:40AM (#28838152)
bit more self-explanatory `it => Object.prototype.toString.call(it).match(/^\[object (\w+)]/).pop()`