Filtering with Type Predicates and Generics
Before we start on the solution, let's take a closer look at the error message in the DOMNodeExtractorConfig
:
Argument of type '(node: T) => Result' is not assignable to parameter of type '(value: unknown, index: number, array: unknown[]) => TResult'
Essentially the error message tel
Transcript
0:00 Before we solve it, let's actually look at this error down here because this one's really interesting. What we've got here is it's basically saying, "Argument of type node T result is not assignable to type value unknown index, blah, blah, blah, result."
0:14 It looks like the parameters of node and value are incompatible because node type unknown is currently not assignable to type T. That means that we're basically taking an array of unknown nodes. We're filtering them. What we're supposed to be passing here is a type predicate that's going to filter the unknown ones out.
0:37 God, I can't speak anymore. Then just return us the ones that conform to T. Which means that is node is supposed to be a type predicate of some sort. How can we represent this well? We can actually, instead of this boolean, we can say node is T. That's it. That's the solution.
0:59 What this is doing then is it's passing in a function. This is div elements down here. This is saying element is div element. It means that this div is inferred as HTMLDivElement. We can create a new one here if we want to. We can say const is body, let's say, is span elements, for instance.
1:19 Let's create this function, which is going to be elements unknown. In fact, I'm going to just copy and paste the one from up here. Then I'll just change the results of that so we end up with span element, HTMLSpanElements. We're getting these from lib.dom.d.ts, by the way, or global.d.ts or something.
1:42 Now what we get is span element. We can put that in here. We suddenly end up with this span in this slot, which is just so, so cool that we can get the inference from a type predicate in order to make this work. This is really, really useful. I found this useful for when I was building quite a complicated thing, which was an AST node analyzer.
2:08 I was able to pass in things from an external library, which was babel, I think, that had a lot of is this or is that. If you're dealing with lots of different types of elements and you have a few type predicates that you're building in here, it's really cool that you can use this node is T or input is T, or whatever you want it to be, in order to use type predicates with generics to get this really amazing inference.