Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Control flow] Array filter with typeguard works differently following array initial value #60108

Open
paulsouche opened this issue Sep 30, 2024 · 1 comment
Labels
Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Milestone

Comments

@paulsouche
Copy link

paulsouche commented Sep 30, 2024

🔎 Search Terms

filter + typeguard + control flow + strictNullChecks

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about filter + typeguards + control flow + strictNullChecks

⏯ Playground Link

https://www.typescriptlang.org/play/?strict=false&noImplicitAny=false&strictFunctionTypes=false&strictPropertyInitialization=false&strictBindCallApply=false&noImplicitThis=false&noImplicitReturns=false&alwaysStrict=false&esModuleInterop=false&declaration=false&target=0&jsx=0&module=0&ts=5.6.2&experimentalDecorators=false&emitDecoratorMetadata=false#code/MYewdgzgLgBATgQwO4C4bTgSzAcwNoC6MAPjAIJyICeAPBtjiTGAK4A2bAfDALwyEBuAFBDQkWADNMbKAFM4sgCZp6uQr3jIAdFJnyAFPuiyADiqhZcTVhwCU50zEwR0Fhr25QqJ2SAmvHHiCYAHJVHBDbGAB6aJgAaQB5ETFoV0scACVkcwz1UgpqOjcrUhsuDTwAIhM2EBMqgmFRcDTwgDFpOQVldIZ1PnDspB0ugyM5Mz7S5nY2ewCTJxdwjxgvHz9F3mCwkoio2ITklvFZjmHc-qICygRaVbK57j48cqaU1thyzr0eq7URD45WGoz+hmMU0e53mDiWzmmjB4nm8vn8kJ2fD2GUiMTiiXinzO5QACmwWBAAMr7S6I-LkO4PfbWZ6VGp1BoAGhhH1OaVJ5Kp+1+3SUAPwQJhZIp1IyoN03Qhk3FLLscOWiLWGzR2yCWPCuKOBKEQA

💻 Code

const raw: string[] | (string | null)[] = [];

const filtered: string[] = raw.filter((step: string | null): step is string => typeof step === 'string') // KO
// Type '(string | null)[]' is not assignable to type 'string[]'.
const raw: string[] |(string | null)[] = ["plop", null];

const filtered: string[] = raw.filter((step: string | null): step is string => typeof step === 'string') // OK no error

🙁 Actual behavior

There is a strange difference in control flow when you filter nullish values in an array regarding the declaration of that array. This is definitely a edge case. The type string[] | (string | null)[] comes from an union type in my case.

🙂 Expected behavior

No difference and typeguard should work (regardless the fact it is valid).

Additional information about the issue

I first thought it was a regression due to #57465 but I tested it on several version. The issue has always been here. I looked into a lot of issues about typeguards and filters but unfortunately, could not find one similar to my issue 😢

Thanks anyway for the great job

@Andarist
Copy link
Contributor

Andarist commented Oct 1, 2024

It feels like a duplicate of #60006 . However, the experiment from #60036 doesn't help this case.

When combining union signatures with type parameters those have to be identical. They are not the same here because they have different constraints (S extends string vs S extends string | null). So those signatures you'd like to be used here are discarded within getUnionSignatures and only the non-filtering ones are left as viable ones.

@RyanCavanaugh RyanCavanaugh added Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases labels Oct 16, 2024
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Oct 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Projects
None yet
Development

No branches or pull requests

3 participants