-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Several issues with strict property checks and definite assignement assertion #20740
Comments
I agree this feature is likely to cause new errors in existing code which is why we've placed in it the
I wouldn't characterize it as a hack. It is an explicit acknowledgement that the particular property is initialized by some external mechanism that isn't visible to the type checker (or the casual reader of the code). Some would even argue it is good from a documentation perspective.
Agreed on both of these. |
I think the idea of this feature is good too, I just think the practical solutions may not be good or enough as they are now. I understand that it's normal in strict mode to have new errors raising. But normally the new errors are about code that was already badly designed before, but undetected. The problem here is that it raises a lot of error for code that is well designed, and so to be compliant it needs a code which is not classis JS in too many places. Wouldn't it be possible for TypeScript to automatically acknowledge other mecanisms (like decorators) which are in charge to initialize properties, instead of having to manually use |
#20166 is specifically designed to make this possible where this was out of the visibility of CFA. Currently we have no choice but to use the null assertion operator. Decorators not augmenting types has been there as long as decorators have been supported. I would love to see some sort of ambient decorators and that is still on the long term roadmap, but it is clearly a challenging situation of providing the sort of syntax necessary to describe all the possible things that a decorator could do. There isn't a solid concise proposal for this sort of syntax and I am really glad we have at least something that overrides CFA at level that persists compared what we had before. I would be really surprised that #20166 is causing you errors, it is an escape hatch to deal with other errors. We (@dojo) always expect a level of refactoring when upgrading versions of TypeScript. We use
BTW, the core team does test against real world projects. |
@cyrilletuzi Angular's language service will support this syntax when Angular itself is updated to support 2.7 and the language service is updated with the new version of the compiler. This error is currently produced because the language service is using 2.5 to compile syntax introduced in 2.7. Our current plan is to support 2.6 in 5.2 of Angular and 2.7 in the next minor release of Angular after 2.7 is released. I also agree with Anders that adding @ahejlsberg, you might consider allowing libraries to declare a decorator such as Although, not directly helpful for Angular, you might also consider allowing a base class to declare constructor helper methods. |
Again, the problem is not refactoring in itself. Refactoring because of badly designed code is OK. For example, the TS 2.6 But refactoring (and a huge one) when the code is well designed but TypeScript is not able to detect it, it is not the same thing. Again, I think too strict property checks is a good idea, but UX should be considered too and the definite assignement assertion solution doesn't seem user-friendly to me in its current state. It will add complexity to JavaScript and TypeScript beginners when it could be TypeScript doing a better job. If TypeScript is able to manage things like decorators, it would be a far better solution and it would be relevant to not rush. |
In my opinion, the fact that strict property checks had to immediately be accompanied by the definite assignement assertion shows there is a problem somewhere. The reasoning behind the
This reasoning would be better :
|
Yes, we discussed that option, but until the decorators proposal reaches stage 3 we're unlikely to go there (we already have the headache of reconciling our current decorator support with the final proposal).
Right, although it think this it is less obvious how to generalize this one. @cyrilletuzi: We're definitely committed to improving this feature over time (e.g. by recognizing special decorators), but the design team feels that, in the balance, the feature is valuable enough in its current state to be a |
Given the vast majority of decorators are Angular ones that initialize a property, should we just assume any decorator on a property is equivalent to |
I think you could strike |
Consider allowing a postfix @Component({...})
export class MyComponent {
private myData: MyData;
ngOnInit!() {
myData = calculateMyData();
}
} In this example, the You can then imagine a class transformer such as, type AngularComponent<T> = T & { ngOnInit?!(): void; };
function Transformer<T>(clazz: Class<T>): Class<AngularComponent<T>> {
...
} which says something like, if A class decorator would then be interpreted as if it was a class transformer and the type of the class would be the function's return type. This is general in that it can specify any arbitrary functional composition (or higher order classes) that can be described using a function type. A similar thing could be done with member annotations using mapped types if the name of the property as a type was supplied as an implied type parameter to the decorator. |
Another feedback : same problem in native Web Components, where initialization is not done in As it's a standard, TypeScript should check initialization in |
|
Ref #8476 |
FWIW, I do hope the TS team can solve this issue without the option: if you choose to opt-in on I just want to highlight the comment from @kitsonk:
This is what I felt as well, many frameworks are built using this pattern, I guess it is the IoC pattern, Inversion of Control? Maybe we should call it Inversion of Construction instead. When some controls are inversioned, it relies on annotations provided by decorators. The constructions(controls) of properties is inversioned here. Maybe I'm not the average TS programmer out there, but the negative impact defined as the number of lines of As a developer, I trust my framework to provide me with the construction of my properties. Because the construction was inversioned. What is missing is a something to tell the compiler, so it can trust the framework as well. Now, when errors are thrown in my definitions, it means that the compiler doesn't trust the framework. I don't think telling people to turn off the flag or put |
A similar use case is using Immutable.js record types with typescript. Just ran across this with the recent VS Code upgrade. I'm also an Angular developer and use Immutable.js (with TypeScript) extensively. I have been bitten on more than a few occasions where I assumed an Angular In the Angular scenario - this reminds me of Dependency Injection frameworks doing property injection. Yeah, it's possible - but is kind of sloppy. Perhaps Angular can/should adopt putting I would like to see some ideas for more usable/flexible class construction/instantiation in TypeScript that would be more amenable to Library/Frameworks and general application development. This would include both the usage/construction of the object (similar to C# object initializers syntax), but also the development experience of implementing the constructor/object (in this case Angular components), perhaps something akin to a Java anonymous inner class for a constructor parameter that behaves as a partial or extension to the class it is constructing. |
Closing this, as the discussion has ended and no action has been planned. |
TypeScript Version: 2.7.0-dev.20171214
This issue is about the new strict property checks #20075 and definite assignement assertion #20166.
@ahejlsberg @mhegazy @DanielRosenwasser @RyanCavanaugh Did you guys test this new feature on real world projects ? Because as it is now, it could lead to a huge (negative ?) impact. It may need more thinking/fixing before landing in stable.
As VS Code Insiders now uses TS 2.7, when opening my Angular project (which is in strict mode), I discovered with surprise that now half my files contain errors (all my components) due to this new feature. And trying to get compliant with this led to many problems, some of them with no solution currently.
Take this very simple Angular code :
movie
property now raises an error as TS can't know it will be initialized by an Angular mecanism.Let's look at the solutions to be compliant with the new strict mode feature :
Unfortunately, that's not possible here, as an object is expected. Only solution would be to set
null
by default, but then strict mode would raise another error due tostrictNullChecks
. So you would allownull
as a type, but then TS will scream everywhere you usemovie
inside the class and force you to check if it's not null, when you already know very well it's not. So it's a mess.Another problem : this feature checks the constructor, but in Angular you often must wait another callback like
ngOnInit
to do your initial stuff.First, in Angular, it would mean quite all the components properties will need this "hack". As in reality, the code is OK, it seems to me it's a too overwhelming solution to just calm down TypeScript. It could lead people to never adopt this feature, and then complicate the usage of the combined
strict
option, as we would need to just activate some individual strict features. Did you guys ask the Angular team what they think about this ?Second, it's now Angular which raises an error in the template, saying
Identifier 'title' is not defined. '<anonymous>' does not contain such a member
. We should verify before landing that the Angular language service is able to fix this issue. @chuckjazThird, TS Lint is not happy too : it's saying
Missing semicolon (semicolon)
just after the!
. It also should be fixed before this feature is landing to stable.The text was updated successfully, but these errors were encountered: