Non-compiling Equal Type

Viewed 29

Reading Building Complex Types in TypeScript Part 2has the following code for Equal Type that does NOT compile for me:

A Type Level Equals

type Equal<A, B> = 
  (<T>() => T extends A ? true : false)
  extends 
  (<T>() => T extends B ? true : false)
    ? true
    : false;

It has several compilation errors. The type is then used subsequently to solve another problem.

Looking for help to solve it as I am digging deeper into TS types.

1 Answers

TL;DR: you are running into automatic semicolon insertion for conditional types. Remove the a line break before extends and things will work:

type Equal<A, B> =
    (<T>() => T extends A ? true : false) extends // okay
    (<T>() => T extends B ? true : false)
    ? true
    : false;

JavaScript, and therefore TypeScript, has the "feature" where you are sometimes allowed to omit an otherwise required semicolon at the end of a statement if it appears at the end of a line; the language will "helpfully" insert semicolons at the ends of lines for you. This is known as automatic semicolon insertion.

In practice this means that you can't always add line breaks everywhere whitespace would normally be allowed; if it is syntactically valid for a semicolon to appear where you've placed a line break, the language might insert one for you. Isn't that nice?

Because conditional types are of the form AAA extends BBB ? CCC : DDD where AAA is a valid type, and since extends is apparently a valid property name:

interface Foo {
    a: string
    extends: number; // <-- okay
}

then the TypeScript compiler sees a possible automatic semicolon insertion hazard before the extends keyword in a conditional type. You're not allowed to put a line break there. See microsoft/TypeScript#21649 for the pull request that implemented this.

If you remove the line beak before extends, your code will compile as desired.

Note that this line break was not present in the original document from which you copied this type; you (or your non-TS-compliant code formatter) must have inserted it and caused this problem.

Playground link to code

Related