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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
tgfactor opened this issue Feb 23, 2021 · 16 comments
Assignees
Labels
area: compiler Issues related to `ngc`, Angular's template compiler area: language-service Issues related to Angular's VS Code language service P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Milestone

Comments

@tgfactor
Copy link

馃悶 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
@gkalpak gkalpak added the area: language-service Issues related to Angular's VS Code language service label Feb 23, 2021
@ngbot ngbot bot added this to the needsTriage milestone Feb 23, 2021
@atscott atscott added area: compiler Issues related to `ngc`, Angular's template compiler comp: docs P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent labels Feb 23, 2021
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Feb 23, 2021
@meblum
Copy link
Contributor

meblum commented Mar 9, 2021

Same issue

@audaxocles
Copy link

I have the very same issue.

@CrisDan1905
Copy link

Same issue, but I'm using Angular 9. I guess it's a bug more related to VSCode or the Angular language service

@z-svoboda-mob
Copy link

I've run into similar, This component requires inline template type-checking, which is not supported by the current environment. These messages live right next to eachother:
https://github.com/angular/angular/blame/master/packages/compiler-cli/src/ngtsc/typecheck/src/oob.ts#L161

They're invoked from the a similar place as well:
https://github.com/angular/angular/blob/master/packages/compiler-cli/src/ngtsc/typecheck/src/context.ts#L275

If I'm understanding correctly, these types of checks aren't possible with inlining which make since that's a big part of how Ivy works. It seems like this is just a missing feature... perhaps the error message has only recently (blame shows changes 8 months ago...? something something vs code extension update using new version of ngtsc?) begun to show what was previously a silent lack of type checking.

@atscott @alxhub sorry for the bother but I see your names on these lines, would you be able to lend some insight?

@atscott
Copy link
Contributor

atscott commented Mar 16, 2021

@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.

zarend added a commit to zarend/angular that referenced this issue Mar 16, 2021
This commit fixes the behavior when creating a type constructor for a directive when the following
conditions are met.
1. The directive has bound generic parameters.
2. Inlining is not available. (This happens for language service compiles).

Previously, we would throw an error saying 'Inlining is not supported in this environment.' The
compiler would stop type checking, and the developer could lose out on getting errors after the
compiler gives up.

This commit adds a useInlineTypeConstructors to the type check config. When set to false, we use
`any` type for bound generic parameters to avoid crashing. When set to true, we inline the type
constructor when inlining is required.

Addresses angular#40963
@z-svoboda-mob
Copy link

That does make sense, it compiles just fine so I've clearly munged some things together in my head.

It's exciting to have this issue resolved and I hesitate to ask for more, but I wonder if that limitation can be removed/maneuvered around?

@z-svoboda-mob
Copy link

Looks like I should be looking over in this ticket: angular/vscode-ng-language-service#1154
This component requires inline template type-checking, which is not supported by the current environment.

@tgfactor
Copy link
Author

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.

zarend added a commit to zarend/angular that referenced this issue Mar 17, 2021
This commit fixes the behavior when creating a type constructor for a directive when the following
conditions are met.
1. The directive has bound generic parameters.
2. Inlining is not available. (This happens for language service compiles).

Previously, we would throw an error saying 'Inlining is not supported in this environment.' The
compiler would stop type checking, and the developer could lose out on getting errors after the
compiler gives up.

This commit adds a useInlineTypeConstructors to the type check config. When set to false, we use
`any` type for bound generic parameters to avoid crashing. When set to true, we inline the type
constructor when inlining is required.

Addresses angular#40963
@atscott
Copy link
Contributor

atscott commented Mar 17, 2021

@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.

zarend added a commit to zarend/angular that referenced this issue Mar 17, 2021
This commit fixes the behavior when creating a type constructor for a directive when the following
conditions are met.
1. The directive has bound generic parameters.
2. Inlining is not available. (This happens for language service compiles).

Previously, we would throw an error saying 'Inlining is not supported in this environment.' The
compiler would stop type checking, and the developer could lose out on getting errors after the
compiler gives up.

This commit adds a useInlineTypeConstructors to the type check config. When set to false, we use
`any` type for bound generic parameters to avoid crashing. When set to true, we inline the type
constructor when inlining is required.

Addresses angular#40963
zarend added a commit to zarend/angular that referenced this issue Mar 17, 2021
This commit fixes the behavior when creating a type constructor for a directive when the following
conditions are met.
1. The directive has bound generic parameters.
2. Inlining is not available. (This happens for language service compiles).

Previously, we would throw an error saying 'Inlining is not supported in this environment.' The
compiler would stop type checking, and the developer could lose out on getting errors after the
compiler gives up.

This commit adds a useInlineTypeConstructors to the type check config. When set to false, we use
`any` type for bound generic parameters to avoid crashing. When set to true, we inline the type
constructor when inlining is required.

Addresses angular#40963
zarend added a commit to zarend/angular that referenced this issue Mar 17, 2021
This commit fixes the behavior when creating a type constructor for a directive when the following
conditions are met.
1. The directive has bound generic parameters.
2. Inlining is not available. (This happens for language service compiles).

Previously, we would throw an error saying 'Inlining is not supported in this environment.' The
compiler would stop type checking, and the developer could lose out on getting errors after the
compiler gives up.

This commit adds a useInlineTypeConstructors to the type check config. When set to false, we use
`any` type for bound generic parameters to avoid crashing. When set to true, we inline the type
constructor when inlining is required.

Addresses angular#40963
mhevery pushed a commit that referenced this issue Mar 18, 2021
)

This commit fixes the behavior when creating a type constructor for a directive when the following
conditions are met.
1. The directive has bound generic parameters.
2. Inlining is not available. (This happens for language service compiles).

Previously, we would throw an error saying 'Inlining is not supported in this environment.' The
compiler would stop type checking, and the developer could lose out on getting errors after the
compiler gives up.

This commit adds a useInlineTypeConstructors to the type check config. When set to false, we use
`any` type for bound generic parameters to avoid crashing. When set to true, we inline the type
constructor when inlining is required.

Addresses #40963

PR Close #41043
zarend added a commit to zarend/angular that referenced this issue Mar 18, 2021
This commit fixes the behavior when creating a type constructor for a directive when the following
conditions are met.
1. The directive has bound generic parameters.
2. Inlining is not available. (This happens for language service compiles).

Previously, we would throw an error saying 'Inlining is not supported in this environment.' The
compiler would stop type checking, and the developer could lose out on getting errors after the
compiler gives up.

This commit adds a useInlineTypeConstructors to the type check config. When set to false, we use
`any` type for bound generic parameters to avoid crashing. When set to true, we inline the type
constructor when inlining is required.

Addresses angular#40963
@andreialecu
Copy link
Contributor

andreialecu commented Mar 19, 2021

I noticed that @zarend's PR was just merged. That's great, as we've just been recently hit by this problem after enabling strict checks.

However, we have a pretty big and complex app, and there seems to be no hint as to what is triggering the error in the first place. We could address it, but it seems very cumbersome to dig for it.

Right now the language server just seems to crash in random places.

From reading the commits on the new PR, it seems that the new behavior is to just use any.

I wonder if any sort of indication about which constructor is failing at could be given during compilation, as a warning?

Or is there any other way to troubleshoot this?

Edit: nevermind, I missed the code where an actual diagnostic log is printed. I was originally looking for some tests to assert that the proper errors are thrown, but they seem to be missing.

@atscott
Copy link
Contributor

atscott commented Mar 19, 2021

Fixed by 09aefd2

@atscott atscott closed this as completed Mar 19, 2021
mhevery pushed a commit that referenced this issue Mar 19, 2021
)

This commit fixes the behavior when creating a type constructor for a directive when the following
conditions are met.
1. The directive has bound generic parameters.
2. Inlining is not available. (This happens for language service compiles).

Previously, we would throw an error saying 'Inlining is not supported in this environment.' The
compiler would stop type checking, and the developer could lose out on getting errors after the
compiler gives up.

This commit adds a useInlineTypeConstructors to the type check config. When set to false, we use
`any` type for bound generic parameters to avoid crashing. When set to true, we inline the type
constructor when inlining is required.

Addresses #40963

PR Close #41268
@alxhub
Copy link
Member

alxhub commented Mar 22, 2021

@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.

@MuMaestro
Copy link

MuMaestro commented Mar 30, 2021

Hello,
This is a fixed issue, and it's in ver 11.2.7. But I can't find where to enable it. I've tried to put useInlineTypeConstructors: true in angularCompilerOptions in my tsconfig. Still vscode warns that inline type-check is disabled. Is the config name wrong ? It's not configurable ?

@atscott
Copy link
Contributor

atscott commented Mar 30, 2021

@MuMaestro - What specifically is the warning you're getting and in what context?

There isn't a warning produced for directives with generic types anymore so it can't be that. I'm guessing what you're seeing is "This component requires inline template type-checking, which is not supported by the current environment." rather than "This component uses a directive which requires an inline type constructor..."
That's a separate problem and happens under the following conditions:

  1. The component class is not exported
  2. The component uses generic types with constraints. We have more sophisticated logic for directives in place (that's what this issue was addressing) but haven't extended that to components.
  3. The component uses a pipe that isn鈥檛 exported

Would you mind filing a new issue for this along with a reproduction?

@MuMaestro
Copy link

@atscott here it is: issue

Hope this it's not hard to solve :)

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators May 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: compiler Issues related to `ngc`, Angular's template compiler area: language-service Issues related to Angular's VS Code language service P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

No branches or pull requests