angular: Angular 11.2+ language service error for inline type constructor not supported by current environment (-998901)

šŸž bug report

Affected Package

@angular/compiler-cli - oob.js @angular/language-service - ivy.js

Is this a regression?

Worked before in version 11.0.x, and I assume 11.1.x because my Visual Studio Code Extension seems to always update on the latest version of Angular language, and this just started happening in the past week.

Description

I am currently using angular-imask and iMask in my Angular 11 projects. I have not touched any aspect of the usage of these plugins in my code for the past two months, and have not had any unusual Visual Studio Code errors pop up, until now. Iā€™ve started to see the following error appear in both the .ts and .html file of the affected components:

ā€œThis component uses a directive which requires an inline type constructor, which is not supported by the current environment. (-998901)ā€

I pinpointed it down to the imask directive I use for my input field (assume moneyMask is a valid mask object that has not been changed for the past two months):

<input type="text" id="someId" name="someName" ... [imask]="moneyMask" [unmask]="true" >

If I were to remove the [imask] and [unmask] directives from my input tag, the VSC error goes away for both the affected .ts and .html component files. But now I have effectively eliminated masking from my input fields.

Important: While this error does appear in VSC, I get no issues after running ng lint (I am using ESLint instead of TSLint), and my project both runs fine locally via ng serve and can built without any errors too. So this seems to be centralized with Visual Studio Code and the Angular Language Service, but I know at some point my development team is going to be asking questions soon about this and it could affect any other directive-based plugins I choose to use in my projects.

šŸŒ Your Environment

Angular Version:


Angular CLI: 11.2.1
Node: 12.20.1
OS: win32 x64

Angular: 11.2.2
... animations, common, compiler, compiler-cli, core, elements
... forms, language-service, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1102.1
@angular-devkit/build-angular   0.1102.1
@angular-devkit/core            11.2.1
@angular-devkit/schematics      11.2.1
@angular/cdk                    11.2.1
@angular/cli                    11.2.1
@schematics/angular             11.2.1
@schematics/update              0.1102.1
rxjs                            6.6.3
typescript                      4.1.5

Running Visual Studio Code version 1.53.2.
Angular Language Service Extension running version 11.2.3

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 19
  • Comments: 16 (7 by maintainers)

Commits related to this issue

Most upvoted comments

@andreialecu, as you mentioned, Zachā€™s PR will address this - thereā€™s very likely no need to change any of your application code.

There is a case that comes up in template type-checking where a directive is generic, and has generic parameter bounds which the template type-checker canā€™t easily copy (for example, this sometimes happens when a directive does <T extends Foo> and Foo is some interface that isnā€™t actually exported). In such cases, the compiler has a ā€œdeoptimizationā€ that it can do to still properly type-check usages of the directive, just less efficiently than it otherwise could. The Language Service, on the other hand, doesnā€™t have access to the deoptimization, and previously could not handle checking such directives.

This case was thought to be exceedingly rare, and so we didnā€™t implement much of a defense against it - the Language Service would give up attempting to check any component that used such a directive.

However, that was naive of us - it turns out this case is less rare than we expected, and such directives do sometimes show up in applications. This kind of code isnā€™t wrong, it still works at runtime and is still processable by the compiler, but in the Language Service it just canā€™t be type checked as cleanly. Instead of a hard error, then, we decided to empower the Language Service to still handle such directives by backing off on the generic types, and inferring any instead. This sacrifices a bit of accuracy to allow the directive (and thus the template) to still be understood by the LS.

Falling back to any does affect type inference, but in very minor ways:

  • input assignability checks on the directive to inputs which use the generic type may not report errors (but the compiler will still catch them).
  • if the generic type flows out from the directive into a context (e.g. with ngTemplateContextGuard), then this type will also be impacted. This case should be very rare, as often such generics are used in more places and thus types are likely to be properly exported. Again, the compiler will process this case correctly regardless.

@z-svoboda-mob - This is purely a limitation of the language service. The compiler itself will use the correct types during compilation. Some generic directives/components require the compiler to make in-line edits to the source by generating a static method which the type check files can import and use to get the correct type. We canā€™t make this in-line edit in the language service because that would mean editing the file itself.

@zarend is addressing this in #41043 - this will be only an informational diagnostic and the language service will use any for the type rather than exiting and providing no information at all.

@tgfactor For the record, the old version of the language service did not do a better job of determining the correct types of the generics (itā€™s actually much worse), it just doesnā€™t produce an error diagnostic. In addition, it is no longer in active development and will be officially deprecated/removed in an upcoming version.

That said, the behavior in the current implementation of the Ivy Language Service is unacceptable because it not only produces the error, but also ends up exiting out of the type checking when it encounters this scenario. @zarendā€™s PR should be merged this week or next and it will be included whichever weekly release follows that.

FYI, since my initial report, I discovered that these errors were happening due to the ā€œAngular: Enable-experimental-ivy-promptā€ and ā€œAngular: Experimental-ivyā€ checkboxes being selected. Go to the Angular Language Services extension in VSC, and click on the gear for Settings. If both checkboxes are active, simply uncheck them, restart VSC, and the errors should go away.

I do credit them for helping me spot a design flaw in the project, but it was annoying that they were selected and giving me weird errors I had no idea about. Deactivating the experimental options should solve the problem.