Language service does not infer generic type from component @Input
See original GitHub issue🐞 bug report
Affected Package
The issue is caused by package @angular/language-service
Is this a regression?
No. To my knowledge it has never worked.
Description
I’ve found several issues when using generic components.
Given this generic component
@Component({
selector: "test",
template: "",
})
export class TestComponent<T> {
@Input() myData: T[] = [];
@Output() out = new EventEmitter<T[]>();
public data: T[] = [];
}
Then when listOfPeople: Person[]
<test #peopleTest [myData]="listOfPeople" (out)="doStuff($event)"></test> <!-- $event: T[] is not a valid input to doStuff(string) -->
<ng-container *ngIf="peopleTest.data as data2"> <!-- no hover over `as data2` -->
{{ data2 }} <!-- data2 is any, should be Person[] -->
</ng-container>
<ng-container *ngIf="peopleTest.data == listOfStrings"></ng-container> <!-- these should not be comparable -->
<ng-container *ngIf="peopleTest.data[0] == singleString"></ng-container> <!-- if `peopleTest.data == listOfStrings` is comparable, why isn't this? -->
<ng-container *ngIf="peopleTest.data[0] == singlePerson"></ng-container> <!-- these should be comparable -->
While most of these we can live without. The 2nd, that being data2
is any, is a real pain point.
Here’s a real world example where losing the type becomes painful.
<nz-table #basicTable [nzData]="listOfPeople">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Address</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of basicTable.data"> <!-- no hover over `let data` -->
<!--
data is any, should be Person
This opens up for silent typo errors etc
Also refactor tooling doesn't work on these
-->
<td>{{ data.name }}</td>
<td>{{ data.age }}</td>
<td>{{ data.address }}</td>
<td>
<a>Action 一 {{ data.name }}</a>
<nz-divider nzType="vertical"></nz-divider>
<a>Delete</a>
</td>
</tr>
</tbody>
</nz-table>
🔬 Minimal Reproduction
clone https://github.com/snebjorn/angular-n3eeck
open app.component.html
and observe the errors and missing type info
🔥 Exception or Error
Referring to the above examples:
data
anddata2
should infer the correct generic type (Person[]
)(out)="doStuff($event)"
should give an error as doStuff only accepts a string parameter*ngIf="peopleTest.data == listOfStrings"
should not be comparable*ngIf="peopleTest.data[0] == singlePerson"
should be comparable
🌍 Your Environment
Angular Version:
Angular CLI: 10.2.0
Node: 12.16.1
OS: win32 x64
Angular: 10.2.3
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1002.0
@angular-devkit/build-angular 0.1002.0
@angular-devkit/core 10.2.0
@angular-devkit/schematics 10.2.0
@angular/cdk 10.2.7
@angular/cli 10.2.0
@schematics/angular 10.2.0
@schematics/update 0.1002.0
rxjs 6.6.3
typescript 4.0.5
Anything else relevant? This is an continuation of #33055 ish
Issue Analytics
- State:
- Created 3 years ago
- Reactions:7
- Comments:6 (3 by maintainers)
Top Results From Across the Web
Returned type of a function is not inferred when it's ...
Returned type of a function is not inferred when it's declared as generic from the function's argument · Ask Question. Asked 10 months...
Read more >How To Use Generics in TypeScript
TypeScript here is inferring the generic type from the calling code itself. This way the calling code does not need to pass any...
Read more >TypeScript for React Developers
TypeScript, Java, and a bunch of other languages have static typing that will define a type associated with a variable. The type will...
Read more >Typed Forms
If you want to have multiple different element types inside the array, you must use UntypedFormArray , because TypeScript cannot infer which element...
Read more >Generics - F# | Microsoft Learn
When you use generic functions or methods, you might not have to specify the type arguments. The compiler uses type inference to infer...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
FWIW, we’re also using ng-zorro and work around this issue, as well as all other typing shortcomings in templates (I’ve posted this in those other issues as well), using something like
with
It’s not ideal as technically it’s just a type assertion, but it avoids the any and you’re more likely to change the
Person
type structurally than replace the type of the data altogether anyway.Overall it’s definitely a little disappointing how quickly the typing abilities of Angular fall apart given that it was built on TS with the purpose of being type-safe. There is supposed to be ongoing work for the language service with Ivy though, but I have no idea what that entails in detail.
Generic type arguments on components are, in my experience, definitely not exotic but common and I wish this would work better out of the box as well.
Seems something is coming down the pipe 🎉
https://blog.angular.io/version-11-of-angular-now-available-74721b7952f7