tree-sitter / tree-sitter-typescript

TypeScript grammar for tree-sitter
MIT License
335 stars 104 forks source link

`conditional_type` should use `prec.right` instead of `prec.left`. #231

Closed kevinbarabash closed 12 months ago

kevinbarabash commented 1 year ago

The following piece of code is valid but it is parsed incorrectly:

type GetTypeName<T extends boolean| number | string> = 
            T extends boolean ? "boolean" : 
            T extends number ? "number" : 
            "string";

Here's a link to the TypeScript Playground showing that the snippet above is valid JavaScript or TypeScript: https://www.typescriptlang.org/play?#code/C4TwDgpgBA4hwBVwQHIEMC2EA8CoQA9gIA7AEwGcoAjAe1oBsI0SAfKEgVw2ogCco7CsD4BLEgHMAfFAC8UAFBRlK1cryFi5KnUbMSUAPxQARLqYsTUAFyK19qBqKlKHbrwHGTXHvyu2lB1UTYTFJEwBuIA

This is the output from https://tree-sitter.github.io/tree-sitter/playground:

program [0, 0] - [4, 0]
  type_alias_declaration [0, 0] - [3, 21]
    name: type_identifier [0, 5] - [0, 16]
    type_parameters: type_parameters [0, 16] - [0, 52]
      type_parameter [0, 17] - [0, 51]
        name: type_identifier [0, 17] - [0, 18]
        constraint: constraint [0, 19] - [0, 51]
          union_type [0, 27] - [0, 51]
            union_type [0, 27] - [0, 42]
              predefined_type [0, 27] - [0, 34]
              predefined_type [0, 36] - [0, 42]
            predefined_type [0, 45] - [0, 51]
    value: conditional_type [1, 12] - [3, 20]
      left: conditional_type [1, 12] - [2, 13]
        left: type_identifier [1, 12] - [1, 13]
        right: predefined_type [1, 22] - [1, 29]
        consequence: literal_type [1, 32] - [1, 41]
          string [1, 32] - [1, 41]
            string_fragment [1, 33] - [1, 40]
        alternative: type_identifier [2, 12] - [2, 13]
      right: predefined_type [2, 22] - [2, 28]
      consequence: literal_type [2, 31] - [2, 39]
        string [2, 31] - [2, 39]
          string_fragment [2, 32] - [2, 38]
      alternative: literal_type [3, 12] - [3, 20]
        string [3, 12] - [3, 20]
          string_fragment [3, 13] - [3, 19]

This is what the output should be:

program [0, 0] - [4, 0]
  type_alias_declaration [0, 0] - [3, 21]
    name: type_identifier [0, 5] - [0, 16]
    type_parameters: type_parameters [0, 16] - [0, 52]
      type_parameter [0, 17] - [0, 51]
        name: type_identifier [0, 17] - [0, 18]
        constraint: constraint [0, 19] - [0, 51]
          union_type [0, 27] - [0, 51]
            union_type [0, 27] - [0, 42]
              predefined_type [0, 27] - [0, 34]
              predefined_type [0, 36] - [0, 42]
            predefined_type [0, 45] - [0, 51]
    value: conditional_type [1, 12] - [3, 20]
      left: type_identifier [1, 12] - [1, 13]
      right: predefined_type [1, 22] - [1, 29]
      consequence: literal_type [1, 32] - [1, 41]
        string [1, 32] - [1, 41]
          string_fragment [1, 33] - [1, 40]
      alternative: conditional_type [2, 12] - [3, 20]
        left: type_identifier [2, 12] - [2, 13]
        right: predefined_type [2, 22] - [2, 28]
        consequence: literal_type [2, 31] - [2, 39]
          string [2, 31] - [2, 39]
            string_fragment [2, 32] - [2, 38]
        alternative: literal_type [3, 12] - [3, 20]
          string [3, 12] - [3, 20]
            string_fragment [3, 13] - [3, 19]

This matches what the TypeScript parser is doing. I verified this using https://astexplorer.net.