-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Improve generic keyof relationship checking for generic conditionals with keyless branch types #49563
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
base: main
Are you sure you want to change the base?
Conversation
…with keyless branch types
Can you give an example of how a particular react libraries would benefit from this? A concrete example of usage would help me understand how widely applicable it might be. |
Hmm, I'm not sure these changes are desirable. See the discussion here. We effectively rely on the fact that |
I dunno, all the cases in the test in this PR seem pretty desirable... |
(also that's unchanged by this PR?) |
With this PR there is no error in the example below where previously there was. The error is desirable because it protects us from accessing through a possibly-null object without requiring local proof that the object is non-null. The thing that saves us is that type NonNull<T> = T extends null ? never : T;
function foo<T>(t: T, k: keyof NonNull<T>) {
t[k]; // Was error, now isn't
}
foo(null, 'foo'); |
If that should be invalid, it should be because |
I'm quite certain that would be a severe breaking change, and it would force checks that are unnecessary because we're already protecting you by having |
Except it's not Point being we can clearly do better here. Using one problem to excuse another isn't a great place to be - both probably need fixing. |
@weswigham do you want to keep working on this? Is there a reasonable path to fixing the |
Originally from #49091. This essentially applies
keyof
to the constraint of a conditional in a deferred way, ignoring branches which don't contribute to the final result set of keys. This allows, eg,keyof (T extends null ? never : T)
to be related tokeyof T
. In addition, intersection members for whomkeyof
returnsnever
are omitted from the relationship check, allowing a deferred effectivekeyof (T & object)
to be related tokeyof T
(which already works when not indirected via a conditional via construction).So in total, given a type like
then
keyof FilterNull<(T & object) | null>
is now able to be related tokeyof T
.Practically, I initially looked into this to support using the conditional-based
NonNullable
in more places, but now that it's just an intersection, this is moreso just for users usingkeyof
over their own filtering conditionals (as is common inreact
libraries nowadays).