What changed in user defined type guards since typescript 2.4

40 views Asked by At

This code works fine with typescript 2.3, but fail with typescript 2.4. Can you explain why?

testFindTypeGuard.ts:

let el: Element;

const nodes: Node[] = [];

const result = nodes.find((n): n is HTMLFontElement => n.nodeName === "FONT");

el = result;

my.d.ts:

interface Array<T> {
    find<U extends T>(predicate: (value: T, index: number, obj: Array<T>) => value is U): U | undefined;
}

error message:

error TS2322: Build:Type 'Node' is not assignable to type 'Element'.

1

There are 1 answers

0
Fenton On

In order to make your example work as you expect, you need to describe U to the compiler. It isn't making the conceptual leap of widening the applicability of your type guard automatically.

When you use a type guard as part of an if-statement, it will change the types for you (in both the if and the else). But in your example, you need to pass the type argument to get to where you want to be:

const result = nodes.find<HTMLFontElement>((n): n is HTMLFontElement => n.nodeName === "FONT");

The compiler is smart enough to determine when things don't stack up, the following will give you an error:

const result = nodes.find<HTMLDivElement>((n): n is HTMLFontElement => n.nodeName === "FONT");

If you think the compiler was doing a better job of this on a previous version, you may want to raise an issue on GitHub... although you may have done so already.