microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.11k stars 12.37k forks source link

functions with destructuring parameters are not inferred as type predicate correctly #59497

Open Zzzen opened 1 month ago

Zzzen commented 1 month ago

πŸ”Ž Search Terms

infer type predicate, destructuring

πŸ•— Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAGlC8UDeVSQFxQOQEEsG4oBDTAZ2ACcBLAOwHMoBfKAH2VXAkywCECoARmUq0GjfACgANhGBQAHqUwwA2gF0EUdZIkB6XVFIALAPYBXKQBMoNE3IgUKJihIDGJmuSgAzKlOAOEJYAjJgoaFzYeIQkhiL0TOqaihJQUAB0vv4OABQ54ZxMAJQIAHwckAjwiLhYRTrunnJZARRBAExhFZG1McLUCYxJiClpmX6tOfJlCukRVTV49RJAA

πŸ’» Code

type X = { type: 'A'; a: string } | { type: 'B'; b: string };
let xs: X[] = [];

// should not error
const filtered1: { type: 'A'; a: string }[] = xs
  .filter(({ type }) => type === 'A');

const filtered2: { type: 'A'; a: string }[] = xs
  .filter(x => x.type === 'A');

πŸ™ Actual behavior

error on filtered1

πŸ™‚ Expected behavior

not error on filtered1

Additional information about the issue

No response

Andarist commented 1 month ago

That's (partly) because there is no identifier to use there:

const filtered1: { type: 'A'; a: string }[] = xs
  .filter(({ type }): ??? is { type: "A"; a: string; } => type === 'A');

One could be generated though but it would slightly go against the recent "reuse as much as possible from the source file" goal. It would require replacing the whole binding pattern with an auto-generated identifier

miguel-leon commented 3 weeks ago

But there is an identifier there: type. It would be beautiful for the predicate to be:

const filtered1: { type: 'A'; a: string }[] = xs
  .filter(({ type }): type is "A" => type === 'A');
Andarist commented 3 weeks ago

Sure, but then you'd have to make this a valid type predicate because it errors today with:

A type predicate cannot reference element 'type' in a binding pattern.(1230)

Not impossible but it asks new questions about the design of how this should work.