You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Feb 26, 2024. It is now read-only.
Repository navigation
This repository was archived by the owner on Feb 26, 2024. It is now read-only.
void and undefined confusion with incremental clutz #695
That is an error in TypeScript, because 'void' is not 'undefined' assignable. One answer is to emit 'string | void' for the interface too. Generalizing, if the type is union in a return position it need to use 'void' instead of 'undefined'. Note that as far as I can tell closure does not differentiate void and undefined (they are pure type synonims).
Because, we convert undefined in a return position to void to be more TypeScript-y. Maybe that was a mistake, and we should just emit undefined uniformly :/
And to answer my question - "why this works in total mode" - it works because with plainly @override closure reports the interface type (not the inferred type).
I have reservations because of this situation. Users might already have fn that accept string | undefined and when going through closure they will get assignability errors, that cannot trace back to the original .js source.
declareinterfaceI{f(): string|undefined|void;}functionsomeOtherF(x: string|undefined){}functionf(x: I){someOtherF(x.f());// type error here}
replace '@OverRide' with an explicit type annotation, because TypeScript does not have anything like @OverRide. If one redefines a method, they have to retype all the types (otherwise they are any).
Fundamentally if you have the JS equivs of these in different compilation units:
class A { foo(): A|undefined { ... } }
class B { /** @override */ foo() { return undefined; } }
Then there's no way we can rely on inference to pick the proper return type of foo for B. That is an argument for any I guess, separate from the void return problem.
Yep, which means one answer could be add 'return undefined', which has the same downside that some of these cases are in libraries that oppose changes just so that they are consumed by clutz.
Activity
evmar commentedon Feb 16, 2018
is legal JS code at runtime, and probably the intended use of this API, so I think returning
voidis not what we want.Rather, I think this is just another case of inference where we should add an annotation on the subclass.
rkirov commentedon Feb 16, 2018
If the input is:
we still emit:
Because, we convert
undefinedin a return position tovoidto be more TypeScript-y. Maybe that was a mistake, and we should just emitundefineduniformly :/rkirov commentedon Feb 16, 2018
And to answer my question - "why this works in total mode" - it works because with plainly
@overrideclosure reports the interface type (not the inferred type).LucasSloan commentedon Feb 23, 2018
One way to solve this would be to add void to methods that have type unions that include undefined. Thus
Would be translated to:
And implementing that interface with a void method would be fine.
rkirov commentedon Feb 24, 2018
I have reservations because of this situation. Users might already have fn that accept
string | undefinedand when going through closure they will get assignability errors, that cannot trace back to the original .js source.rkirov commentedon Mar 21, 2018
Two other answers here are:
I am leaning towards the second answer.
evmar commentedon Mar 21, 2018
Fundamentally if you have the JS equivs of these in different compilation units:
Then there's no way we can rely on inference to pick the proper return type of
fooforB. That is an argument foranyI guess, separate from the void return problem.rkirov commentedon Mar 21, 2018
Sorry, I am not following, isn't the correct type output:
This is valid TS, a subclass can change the return type as long it is a subtype (functions are covariant in the return position).
evmar commentedon Mar 21, 2018
Ah you are right. It's only if foo has no return statement and we infer void where this will break.
rkirov commentedon Mar 21, 2018
Yep, which means one answer could be add 'return undefined', which has the same downside that some of these cases are in libraries that oppose changes just so that they are consumed by clutz.