fix: type checking for union message types#2290
Conversation
|
@ihardlight is attempting to deploy a commit to the next-intl Team on Vercel. A member of the Team first needs to authorize it. |
|
Hey @ihardlight, thanks for opening this PR! I unfortunately want to push back here though. I recommend to validate messages across locales like it's currently shown in the validating messages docs. This validation goes further than just checking for missing keys. Additionally, the type computation is already somewhat expensive, I'd like to avoid further conditions here that could decrease performance. I hope you can understand! |
eb333df to
2977970
Compare
|
You are correct. I have decided to implement a further improvement first, adding performance tests for TypeScript in a separate PR: #2311 This will help to avoid unexpected degradation in speed for type checking in the future.
I have made an update and the current version has a similar number of ‘Instantiations’ but a reduced number of ‘Types’. This may improve performance. https://github.com/ihardlight/next-intl/actions/runs/25076802176/job/73471474816 PS. "Check time" and "Total time" may be noisy, please do not judge PR by them. Locally, they can show actual reduced time after my changes. Thank you in advance. |
… in all union members
3c14500 to
fb9c0c8
Compare
|
There's also related discussion in #2296 — we should really be careful here. Sorry, I'm currently just a bit short on time and this isn't my top priority right now. |
|
@amannn In the updated version, I have reduced the number of created types. I have included benchmarks as proof. Please review the PRs with performance tests and this one. It may also resolve the related bug. |
Fix type-safe message key resolution for union message schemas
Summary
This PR fixes a type inference issue in message key resolution when the messages object is defined as a union type.
Previously, keys that were not present in all union members could be incorrectly accepted by the type system, which weakened compile-time safety and allowed invalid translation keys to pass unnoticed.
Example of the issue
Given a union of message schemas such as:
MessagesEnincludesmeta.titleandmeta.descriptionMessagesEsincludes onlymeta.titlethe key
meta.descriptionshould be rejected, because it does not exist in every union member.However, before this fix, TypeScript could incorrectly treat such a key as valid in some cases.
Root cause
The key resolution logic did not properly exclude paths that evaluated to
neverfor some union members. As a result, keys that were missing in part of the union could still be considered valid due to TypeScript’s distributive behavior.What changed
The message key filtering logic was updated to explicitly detect
never-resolved paths and exclude them from the allowed key set.This ensures that:
Impact
Validation
The change is covered by type-level test cases that verify: