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

Use before declaration false positive when combined with binding exports #14679

Closed
Jessidhia opened this issue Mar 16, 2017 · 10 comments
Closed
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@Jessidhia
Copy link

Jessidhia commented Mar 16, 2017

TypeScript Version: 2.2.1

Code

import methodFactory from './http-client'

export { httpDelete as delete } // block scoped httpDelete used before declaration
const httpDelete = methodFactory('DELETE')

Expected behavior:

No error. The export declaration makes no use of the variable; what should happen is that httpDelete's TDZ should extend to the delete export, but that happens regardless of the relative position of the export declaration.

Actual behavior:

Two errors in the same line about the variable being used before assignment.

This error is correct in the case of export default and the typescript-specific export =, but not in any other use of export.

@kitsonk
Copy link
Contributor

kitsonk commented Mar 16, 2017

It is use before declaration. The error is valid. The export declaration does make use of the variable as there is an expected assignment. You are making assumptions about how the code is loaded in a loader. While in practice currently, a module loader may not run into a TDZ issue, in practice, the block scoped variable is being used before it is assigned, which is against the language spec.

@aluanhaddad
Copy link
Contributor

Indeed, note that there is no error when using var, and that this will work correctly when using a target module format and loader that properly support live bindings.

@Jessidhia
Copy link
Author

Jessidhia commented Mar 16, 2017

@kitsonk no, that is literally how it is supposed to work according to spec. No evaluation should happen: 1. Return NormalCompletion(empty)..

If any evaluation does happen, it is a bug with your module loader. There is no assignment expected, at all.

If you do need to convert it to commonjs or whatever is the native data structure for your module loader, you will need to either generate a getter, which is required anyway to correctly implement live binding and frozen module shape, or do a delayed assignment.

@Jessidhia
Copy link
Author

Jessidhia commented Mar 16, 2017

@aluanhaddad it will work correctly, which is why it should not be a compile error.

Even the code generated by the playground is (more-or-less) correct, but it will raise a compilation error anyway, even with --modules es2015.

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Mar 16, 2017
@RyanCavanaugh
Copy link
Member

Simple enough fix to not issue this error when the parent is an export declaration

@aluanhaddad
Copy link
Contributor

@Kovensky that's a great point, and I imagine it's one of the reasons that the register format uses var even one targeting es2015. However when TypeScript transpiles to CommonJS, under the es2015 target, it neither uses var nor generates a getter. It just generates an assignment to the exports object. As you say this behavior is not correct. Several issues have been logged, #12522 and #13245 among others, regarding the current behavior.

Thank you for correcting me and for linking to the spec.

@gcnew
Copy link
Contributor

gcnew commented Apr 3, 2017

Does this apply to classes?

The current nightly (typescript@2.3.0-dev.20170403) raises an error when exporting classes before their declaration. It's a relatively recent change. Two week ago the following code was valid.

export { XYZ }
//       ~~~
// XYZ.ts(1,10): error TS2449: Class 'XYZ' used before its declaration.

class XYZ {
}

@RyanCavanaugh
Copy link
Member

@gcnew that should be valid too. Almost certainly the same root cause.

Should be an easy PR if anyone's interested

@gcnew
Copy link
Contributor

gcnew commented Apr 3, 2017

I haven't tried it, but it seems that @Kovensky's PR (#14700) takes care for classes as well. I just saw that he has commented that class exports were miraculously working prior to his change - #14700 (comment).

@mhegazy mhegazy added this to the TypeScript 2.3.1 milestone Apr 17, 2017
@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Apr 17, 2017
@gcnew
Copy link
Contributor

gcnew commented Apr 21, 2017

Unfortunately, the issue still present if you compile with --strict, otherwise it works fine :).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

6 participants