Skip to content

Emitted decorator metadata is different when --isolatedModules is set #8355

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

Closed
jpsfs opened this issue Apr 28, 2016 · 12 comments · Fixed by #9232
Closed

Emitted decorator metadata is different when --isolatedModules is set #8355

jpsfs opened this issue Apr 28, 2016 · 12 comments · Fixed by #9232
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@jpsfs
Copy link

jpsfs commented Apr 28, 2016

Hi,

I'm facing an issue while compiling an Angular 2 application with the IsolatedModules flag set to true.
If IsolatedModules is set to false everything works as expect.

The emitted decorator metadata is different. Is this by design or a bug?

My problem is that my module is getting bigger by the day and using this flag I can greatly improve the CompileOnSave experience.

TypeScript Version:

1.8.7

Code

import * as ng from "angular2/core";

@ng.Decorator({
...
})
export class MyClass{
     constructor(private el: ng.ElementRef) {
     }
}

Expected behavior:
If the isolatedModules flag is set to false:

...
MyClass = __decorate([
      ng.Directive({
            selector: '[my-selector]',
      }), 
      __metadata('design:paramtypes', [ng.ElementRef]) // <<<<<<<<<<<<<<<<<<<
], MyClass);

Actual behavior:

If the isolatedModules flag is set to true:

...
MyClass = __decorate([
      ng.Directive({
            selector: '[my-selector]',
      }), 
      __metadata('design:paramtypes', [Object]) // <<<<<<<<<<<<<<<<<<<<<<<
], MyClass);
@mhegazy
Copy link
Contributor

mhegazy commented Apr 28, 2016

there are differences that are expected in the emit when using this flag, but it should not be functionally different. this sample looks like a bug.

I can not get the different emitted code just using the snippet provided, so there is something else going on. can you share more context from this file.

@jpsfs
Copy link
Author

jpsfs commented Apr 28, 2016

Sorry, it seems that it is a problem within gulp-typescript and not typescript itself.
I'm closing the issue for now.

Nevertheless, here is a repo that can reproduce the bug:
https://github.com/jpsfs/typescript-angular-samples

@jpsfs jpsfs closed this as completed Apr 28, 2016
@ivogabe
Copy link
Contributor

ivogabe commented Apr 28, 2016

@mhegazy I'm confused, has the behavior of isolatedModules been changed? I thought that the project would be compiled file by file, like what transpile does. But that doesn't seem to be what tsc really does?

@mhegazy
Copy link
Contributor

mhegazy commented Apr 28, 2016

The output should be the same as that of transpile. if not it is a bug.

@ivogabe
Copy link
Contributor

ivogabe commented Apr 28, 2016

Gulp-typescript uses transpile, and that emits Object, whereas tsc emits ng.ElementRef. So I think this would be a bug of TypeScript, as I have no idea why gulp-typescript would give a different result otherwise.

@mhegazy mhegazy reopened this Apr 28, 2016
@mhegazy mhegazy added Bug A bug in TypeScript and removed Needs More Info The issue still hasn't been fully clarified labels Apr 28, 2016
@mhegazy mhegazy added this to the TypeScript 2.0 milestone Apr 28, 2016
@mhegazy mhegazy assigned ghost and unassigned rbuckton Jun 7, 2016
@yuit
Copy link
Contributor

yuit commented Jun 14, 2016

@Andy-MS you mind if I take this bug

@ghost
Copy link

ghost commented Jun 14, 2016

OK. Here's what I was testing with:

// @experimentalDecorators: true
// @emitDecoratorMetadata: true
// @target: es5
// @isolatedModules: true

// @Filename: a.ts
export interface X {}

// @Filename: user.ts
import {X} from './a'
declare const decorator: MethodDecorator
export class C {
    @decorator
    myMethod(x: X) {}
}

When a.ts declares X as an interface, the parameter type is output as Object, but when X is a class, it is emitted as a_1.X.
So it appears that even with --isolatedModules, we are looking at information from a different module to affect emit.

@ghost ghost assigned yuit and unassigned ghost Jun 14, 2016
@rbuckton
Copy link
Member

@Andy-MS That is expected. We always serialize an interface as Object.

@yuit
Copy link
Contributor

yuit commented Jun 14, 2016

@rbuckton is this because interface has no value that one can refer to during run-time ?

@yuit
Copy link
Contributor

yuit commented Jun 15, 2016

@ivogabe so there is some inconsistency in our emitted results for sure. I am currently investigating. Though some quick clarification, just wonder why --isolatedModules specified by users make gulp-typescript behaves different since you guys call into TypeScript' api transpile function here and that function will always set isolatedModules to be true. let me know if I misunderstand something here...

@ivogabe
Copy link
Contributor

ivogabe commented Jun 16, 2016

Gulp-typescript has two different compile strategies. When you set isolatedModules, it will use a file based compiler, by calling the transpile function. With incremental compilation this is very fast, since only changed files will be recompiled. If you don't set isolatedModules, it will use a project based compiler. This works with a CompilerHost etcetera, and all files are passed to the compiler.
tsc always takes that second approach.

@ivogabe
Copy link
Contributor

ivogabe commented Jun 16, 2016

The problem is probably that only type information of the containing file is present with transpile. tsc does have type information of all source files but it shouldn't use that in the emit.

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
5 participants