TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Unexpected behavior in extends clause that has two inferred rest types with constraints

Open Oblosys opened this issue 1 year ago • 4 comments

Bug Report

🔎 Search Terms

  • extends constraint inferred rest
  • multiple inferred rest types

🕗 Version & Regression Information

Version 4.7 and higher (including nightly)

  • This is the behavior in every version I tried, and I reviewed the FAQ

⏯ Playground Link

TypeScript playground

💻 Code

type Prefix<A> = A extends [...infer P extends 0[], 1] ? {p: P} : never

{ type Test = Prefix<[0,0,1]> }
// type Test = {p: [0, 0]}

{ type Test = Prefix<[0,0,1,1]> }
// type Test = never

type PrefixSuffix<A> = A extends [...infer P extends 0[], 1, ...infer S extends 0[]] ? {p: P, s: S} : never

{ type Test = PrefixSuffix<[0,0,1,0,0]> }
// type Test = {p: 0[], s: 0[]}

{ type Unexpected = PrefixSuffix<[0,0,1,1,0,0]> }
// type Unexpected = {p: 0[], s: 0[]}

🙁 Actual behavior

Similar to Prefix, which extracts a tuple of leading zeroes and works as expected, I tried to construct PrefixSuffix, to extract both the leading and trailing zeroes. When applied to an array with multiple ones, PrefixSuffix<[0,0,1,1,0,0]> evaluates to {p: 0[], s: 0[]} instead of never.

🙂 Expected behavior

I would have expected PrefixSuffix<[0,0,1,1,0,0]> to evaluate to never, as [0,0,1,1,0,0] cannot extend an array that contains only a single 1. I also would have expected PrefixSuffix<[0,0,1,0,0]> to infer tuple types {p: [0,0], s: [0,0]} rather than {p: 0[], s: 0[]}, but maybe that's just a design limitation.

Oblosys avatar Sep 29 '22 21:09 Oblosys