Zoli recently implemented a new Blocknode, called DeletedEmbed, which we display in place of embeds that have been deprecated. We have a subset of Blocknodes called FeaturedMedia, consisting of a bunch of image / video nodes, and now the new DeletedEmbed. Some issues arose from this addition though. The root cause of the issue was that all other featured media embeds had some sort of string id to them, while DeletedEmbed didn’t. And when Zoli tried to refine the type of a featured media, strange things started happening:
When you hover over this.featuredMedia on line 7, it correctly states that this is indeed a YoutubeVideoJSON, however the id is of an unknown type according to flow, and it can’t be coerced into a string. Why is it an unknown type though? We should be able to tell that YoutubeVideoJSON’s id is a string.
If you hover over id on line 2 though, it tells you it is the type
mixed. The problem lies in DeletedEmbedJSON’s type definition:
It doesn’t have an id, but that’s not the problem. The problem is that it is defined as an inexact object, and that means that it can have any other keys other than those specified. For example, an id. Of any type. So on line 2 of the issue’s example, flow is correct in that this.featuredMedia.id is mixed, it can literally be anything.
Since flow can refine this.featuredMedia’s type to YoutubeVideoJSON, but can’t do it for the id, my guess is that somehow the mixed type got stuck on line 2, when the existence of id was checked. I’m not sure, about it, and it very well could be an error.
However, that’s not the point of this post.
You can define object types as exact object types:
When an object type is defined this way, it means that no other key can be defined on an object of this type other than those explicitly specified. This also solves the above issue, since the id is no longer mixed on line 2, it is now
void | string.
In the future, Flow will switch from inexact object types to exact object types as the default. Here’s a blog post about it. It’s already something that we should be doing more often, as right now we rarely ever define an object with an exact object type notation, although it could lead to a lot less pain points like the above example.