-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
warning on emitDecoratorMetadata for interface in esnext #18008
Comments
|
Thanks for the reply @mhegazy. I understand that's the way it works. My hope was that I outlined such a reasonable case that either you'd
Wouldn't it be much better to just not emit metadata for interface types then? |
As @mhegazy stated, this would preclude decorating any members or member parameters that are not of class types. As metadata emit is an optional and secondary consequence of the presence of a decorator in the source. Annotating all such members with meaningfully metadata emittable types would be prohibitively cumbersome and the resulting code would of far poorer quality in substantial number of cases. There are a substantial number of cases where it is desirable to have metadata enabled but still decorate members they will not result in meaningful metadata but for which the behavior of the decorator is meaningful. For example import {autoinject, bindable} from 'aurelia-framework';
import {Router} from 'aurelia-router';
@autoinject export default class {
constructor(readonly router: Router) {}
@bindable model: {name?: string} = {};
} In the above example, I need the metadata for |
we have no way of doing so at the moment. the emitMetaData uses the runtime value for serialization, this works for classes/enums/primitives, but not for interfaces. interfaces do not exist at run time. |
Somehow I wasn't clear enough when describing my problem, which had to do with the wrong decorator reference being emitted. However, upon further investigation I actually realized that this is a problem with the webpack ts-loader plugin, and not the actual typescript compiler. So my apologies. I've raised the issue there TypeStrong/ts-loader#613 |
My bad again. This really seems to be an issue with Typescript. I opened an issue with ts-loader here TypeStrong/ts-loader#613 (comment) only to realize that they're just using the Typescript language service. So with my recent findings, let me summarize: ts-loader yields different results when running these calls (the option
The first call generates __decorate([
Input(),
__metadata("design:type", Object)
], MyClass.prototype, "myi", void 0); whereas the second generates import { MyInterface } from './my-interface'
//...
__decorate([
Input(),
__metadata("design:type", typeof (_a = typeof MyInterface !== "undefined" && MyInterface) === "function" && _a || Object)
], MyClass.prototype, "myi", void 0); As you can see, the second one references |
But of course, I realize that in order to know that it's just an interface you'd have to keep track of all the files. So maybe it's a big change to support. Maybe |
The difference in emit is intentional. in single-fle-transpile mode (i.e |
First, let me just state that I'm really grateful for your work and that this may come off as fractious. I'm really not - just want Typescript to become as good as it can (and solve my problems of course :)) I understand that single-file transpile means that this error occurs. And that's how it's implemented. But it seems to me this case is an argument for that single-file-transpile is a bad option here. The way I see it, it only becomes an error if:
...i.e. not the ordinary use case, but not really esoteric either. So given that this is the case, moving forward - what would we want it to be? I can see the following options. What is your stance/comment on these?
|
that is not possible. the compiler does not have a way to examine all files, and there is no guarantee it will ever see all files in a single transpilation.
Not sure how that solves the issue. we still have the single-file-transpile mode. |
I think there is a bug here that we should address. the output currentlly is: import { MyInterface } from './my-interface' which is invalid ES6 import. the correct thing to do is to have an import to the module instead, i.e. import * as MyInterface from './my-interface' and then use |
That indeed sounds like a great solution! |
Discussed this with @rbuckton and seems that adding a synthesized import is a big change. the other alternative is to make this an error under
|
Btw, Angular 2 uses this pattern quite a lot, e.g. to detect constructor parameter types. For interface types, it expects the developer to add an extra I've just tripped across this same issue when trying to use the |
@RoystonS that is my use case as well |
@RoystonS Angular's ahead of time compilation (AOT), which seems to be where that Community is going, doesn't even use TypeScript's standards based decorator implementation. They compile away the decorators in a process called lowering which brakes with what was the proposed standard which formed the basis for the TS implementation, and also the current proposed standard, in an incompatible manner. |
@aluanhaddad Guesses about directions (with which I partly disagree btw) for Angular doesn’t affect that this is an issue with Typescript today, not ngc, not in the future. |
I agree with @staeke - it does look like there's a problem today which it would be good to remedy. Let tomorrow's worries look after themselves 😉 |
Is there anything new on this issue? interface Index_ extends Index { }
// ...
@autobind
private getRowHeight(index: Index_) {
return ...;
} |
I think this issue might be set to resolved with the upcoming release of Typescript 3.8 type imports. |
Just encountered this issue in Nuxt.js when using Inversify decorators. At least it seems like it's the same issue.
Without the And this happens because in the resulting build the Thankfully I found this GitHub issue, because it's the only web resource I could find that even remotely explains why this occurs. Maybe this should be documented somewhere more obvious? I guess for now I'll just re-export the interface from somewhere else, but it would be nice to have a real fix where I wouldn't have to do this. Maybe that's not possible, however, so I've also reported this to the package maintainers. This is on TypeScript 4.2.3 and Nuxt.js 2.15.3 |
TypeScript Version: 2.4.2
Code
(using Angular 4)
tsconfig.json
Expected behavior:
Working, no errors. I'd expect no type information emitted for interfaces, as they're only a Typescript compile construct.
Actual behavior:
Although this isn't a bug per se, TypeScript generates a decorator for type information, referencing MyInterface from
otherFile
. Only...this interface doesn't exist runtime. So bundlers (webpack in my case) produce a warning for this (something likeotherFile doesn't export MyInterface
). You can workaround this by creating a local type inmy-class.ts
. Or just accept warnings.The text was updated successfully, but these errors were encountered: