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
Generic type uplifting during assignment (ts 2775) #41047
Comments
This is by design: #32695 All assertion functions must have an explicit type annotation, and your Once you add the explicit type annotation it works:
Or a shorter version:
I don't fully understand their reasoning behind this requirement, but it's there, and that's what the compiler told you. |
I think it is a bug. The fact that Consider this: function assertCustom<T>(
validator: (s: T) => boolean
): (subject: unknown) => asserts subject is T {
return function (subject) {
if (!validator(subject as any)) throw new TypeError(`subject fails assertion`)
return
}
}
const isBool = assertCustom<boolean>(s => typeof s === 'boolean')
const s: unknown = false
// fail
isBool(s)
// ok
expect(isBool(s)).toBe(undefined)
If you hover over |
Your StackBlitz link doesn't work, there's no relevant content.
I'm not sure why you think that is relevant. It being generic or not has no relevance. In your example the second call to In your first call the explicit type annotation is missing. Once you add it it will work. |
Ar, I didn't save the file. Please try again. |
Works now. 👍 But the answer remains unchanged. You also wrote:
Having the correct type is not relevant either when the requirement is to have an explicit type annotation. Your |
I see, that make sense. However I don't see there is an explicit decision made in #32695 that the assertion did not copy to the variable. |
I guess you mean this:
|
I do. :-)
In your example |
Thanks. I can't think of a case that this would trigger a circular reference during analysis. On the other hand, I try doing the same with user-defined type guards. Therefore, it may worth some investigation for improvement. |
User-defined type guards are different from asserting methods because only the latter can cause a statement to become a new node in the control flow graph. This is not a bug or oversight. Obviously if we could just make this work by looking at it and thinking a little, we would have, rather than write out multiple paragraphs in the PR description about the limitations 😉 |
Hi @RyanCavanaugh, thanks! Just want to dealt into this a little bit more. 😛 But I don't understand why the declaration needs to be explicit. So my guess is there are sufficient information available at the assignment to create the variable btw, great TSConf! Thank you! |
The relevant process looks like this:
The first part is syntactic, necessarily, because type information depends on the control flow graph. The second step then proceeds using that control flow graph. What you need to "fix" this is to either make everything in expression space part of the control flow graph, which would be unpalatably slow (both in terms of memory consumed and CPU time consumed walking the graph), or to run some algorithm to keep augmenting the control flow graph and recalculating types until hopefully you reach a fixed point, which would also be very slow. The "explicit type annotation" rule allows TS to augment the graph appropriately at step 1 so that it doesn't have to use information that is only available during step 2 to form a proper CFA graph. |
Ar, got it. Thanks! Great explanation as always. 🌷 |
Search Terms:
generic uplifting
,needs an explicit type annotation.
,2775
This is probably an existing issue but I can't find one.
Code
Expected behavior:
foo
works just likeassertUnknown
Actual behavior:
const foo: (value: unknown, validate?: ((s: boolean) => boolean) | undefined) => asserts value is boolean
Assertions require every name in the call target to be declared with an explicit type annotation.ts(2775)
'foo' needs an explicit type annotation.
Playground Link:
playground
Related Issues:
#37818
This is probably caused by different handling of assignment vs declaration:
One interesting note:
The text was updated successfully, but these errors were encountered: