effective-typescript icon indicating copy to clipboard operation
effective-typescript copied to clipboard

The Making of a TypeScript Feature: Inferring Type Predicates

Open utterances-bot opened this issue 1 year ago • 8 comments

The Making of a TypeScript Feature: Inferring Type Predicates

Effective TypeScript: The Making of a TypeScript Feature: Inferring Type Predicates

https://effectivetypescript.com/2024/04/16/inferring-a-type-predicate/

utterances-bot avatar Apr 21 '24 07:04 utterances-bot

Absolutely fantastic article 👏👏👏

lucapette avatar Apr 21 '24 07:04 lucapette

Great! By the way, the link in There are some notorious examples of this is broken which missing leading h. Currently it's ttps://github.com/microsoft/TypeScript/pull/38839#issuecomment-1160929515

evan-lc avatar Apr 30 '24 03:04 evan-lc

Thanks for the heads up @evan-lc. Should be fixed now.

danvk avatar Apr 30 '24 22:04 danvk

👏👏👏

btoo avatar May 16 '24 20:05 btoo

👏👏👏

lakb248 avatar Jun 17 '24 09:06 lakb248

Hi Dan, without having read everything here and on the PR, I'm wondering what's holding back to resolve the non-null of a null conditional boolean member access: devices.filter(x => x?.enabled) is still (Device | null)[], while devices.filter(x => x != null).filter(x => x.enabled) actually results in Device[]. I'm also wondering what's keeping devices.filter(x => x) from ending up as Devices[], I'd assume the predicate is implicitly typed as (Device | null) => Boolean (because filter() expects a predicate), but apparently it's not that simple.

Either way, thanks for implementing this and nice report of the road leading up to this feature.

mycroes avatar Feb 17 '25 15:02 mycroes

@mycroes It's because type predicates refine the parameter type in a specific way when they return false, not just true. For x => x?.enabled to be a type predicate (x: Device|null) => x is Device, you'd have to have two things be the case:

  1. When it returns true, x would have to have a Device type. (This is the case!)
  2. When it returns false, x would have to be null. (This is not the case.)

So this is not a valid type predicate. Take a look at The Hidden Side of Type Predicates and the Plot Twist section of this post. Of course, this criterion feels overly strict here since filter only cares about the true case. For your examples to work, we'd need one-sided type predicates.

danvk avatar Feb 17 '25 15:02 danvk