Skip to content

Commit f707ef7

Browse files
committed
build: update to TypeScript 5.0
Updates the repo to TypeScript 5 and resolves some errors that came up along the way. The most notable one is that none of the Codelyzer lint rules work anymore, because they depended upon deprecated APIs that have been deleted. I decided to reimplement the rule that asserts that lifecycle hook interfaces are present, but the remaining rules didn't seem that useful so I've removed them.
1 parent ef0fa05 commit f707ef7

File tree

11 files changed

+1287
-1039
lines changed

11 files changed

+1287
-1039
lines changed

integration/yarn-pnp-compat/.yarn/releases/yarn-3.3.1.cjs

Lines changed: 0 additions & 823 deletions
This file was deleted.

integration/yarn-pnp-compat/.yarn/releases/yarn-3.4.1.cjs

Lines changed: 873 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
nodeLinker: pnp
22

3-
yarnPath: .yarn/releases/yarn-3.3.1.cjs
3+
yarnPath: .yarn/releases/yarn-3.4.1.cjs

integration/yarn-pnp-compat/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@
3939
"karma-jasmine-html-reporter": "~1.7.0",
4040
"typescript": "file:../../node_modules/typescript"
4141
},
42-
"packageManager": "yarn@3.3.1"
42+
"packageManager": "yarn@3.4.1"
4343
}

package.json

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@
5656
},
5757
"version": "16.0.0-next.1",
5858
"dependencies": {
59-
"@angular/animations": "^16.0.0-next.0",
60-
"@angular/common": "^16.0.0-next.0",
61-
"@angular/compiler": "^16.0.0-next.0",
62-
"@angular/core": "^16.0.0-next.0",
63-
"@angular/forms": "^16.0.0-next.0",
64-
"@angular/platform-browser": "^16.0.0-next.0",
59+
"@angular/animations": "^16.0.0-next.2",
60+
"@angular/common": "^16.0.0-next.2",
61+
"@angular/compiler": "^16.0.0-next.2",
62+
"@angular/core": "^16.0.0-next.2",
63+
"@angular/forms": "^16.0.0-next.2",
64+
"@angular/platform-browser": "^16.0.0-next.2",
6565
"@types/google.maps": "^3.47.3",
6666
"@types/youtube": "^0.0.46",
6767
"rxjs": "^6.6.7",
@@ -70,18 +70,18 @@
7070
"zone.js": "~0.11.5"
7171
},
7272
"devDependencies": {
73-
"@angular-devkit/build-angular": "^16.0.0-next.0",
74-
"@angular-devkit/core": "^16.0.0-next.0",
75-
"@angular-devkit/schematics": "^16.0.0-next.0",
73+
"@angular-devkit/build-angular": "^16.0.0-next.3",
74+
"@angular-devkit/core": "^16.0.0-next.3",
75+
"@angular-devkit/schematics": "^16.0.0-next.3",
7676
"@angular/bazel": "15.0.4",
7777
"@angular/build-tooling": "https://github.com/angular/dev-infra-private-build-tooling-builds.git#16f13b9e919478d61ec98ce60901f3bdebb5d4e5",
78-
"@angular/cli": "^16.0.0-next.0",
79-
"@angular/compiler-cli": "^16.0.0-next.0",
80-
"@angular/localize": "^16.0.0-next.0",
78+
"@angular/cli": "^16.0.0-next.3",
79+
"@angular/compiler-cli": "^16.0.0-next.2",
80+
"@angular/localize": "^16.0.0-next.2",
8181
"@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#46a6cb28a6ca6a3a7a096656280ed27b02243e9a",
82-
"@angular/platform-browser-dynamic": "^16.0.0-next.0",
83-
"@angular/platform-server": "^16.0.0-next.0",
84-
"@angular/router": "^16.0.0-next.0",
82+
"@angular/platform-browser-dynamic": "^16.0.0-next.2",
83+
"@angular/platform-server": "^16.0.0-next.2",
84+
"@angular/router": "^16.0.0-next.2",
8585
"@axe-core/webdriverjs": "^4.3.2",
8686
"@babel/core": "^7.16.12",
8787
"@bazel/bazelisk": "1.12.1",
@@ -146,7 +146,7 @@
146146
"@octokit/rest": "18.3.5",
147147
"@rollup/plugin-commonjs": "^21.0.0",
148148
"@rollup/plugin-node-resolve": "^13.1.3",
149-
"@schematics/angular": "^16.0.0-next.0",
149+
"@schematics/angular": "^16.0.0-next.3",
150150
"@types/babel__core": "^7.1.18",
151151
"@types/browser-sync": "^2.26.3",
152152
"@types/fs-extra": "^9.0.13",
@@ -165,7 +165,6 @@
165165
"autoprefixer": "^10.4.2",
166166
"browser-sync": "2.26.13",
167167
"chalk": "^4.1.0",
168-
"codelyzer": "^6.0.2",
169168
"cross-env": "^7.0.3",
170169
"date-fns": "^2.28.0",
171170
"dgeni": "^0.4.14",
@@ -216,17 +215,17 @@
216215
"tsickle": "0.39.1",
217216
"tslint": "^6.1.3",
218217
"tsutils": "^3.21.0",
219-
"typescript": "~4.9.3",
218+
"typescript": "5.0.1-rc",
220219
"vrsource-tslint-rules": "6.0.0",
221220
"yaml": "^1.10.2",
222221
"yargs": "^17.3.1",
223222
"zx": "^6.2.4"
224223
},
225224
"resolutions": {
226-
"@angular/build-tooling/typescript": "~4.9.3",
227-
"@angular/ng-dev/typescript": "~4.9.3",
225+
"@angular/build-tooling/typescript": "5.0.1-rc",
226+
"@angular/ng-dev/typescript": "5.0.1-rc",
228227
"browser-sync-client": "2.26.13",
229-
"dgeni-packages/typescript": "~4.9.3",
228+
"dgeni-packages/typescript": "5.0.1-rc",
230229
"**/https-proxy-agent": "5.0.0"
231230
}
232231
}

src/material/form-field/form-field.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
[class.mdc-text-field--no-label]="!_hasFloatingLabel()"
4242
[class.mdc-text-field--disabled]="_control.disabled"
4343
[class.mdc-text-field--invalid]="_control.errorState"
44-
(click)="_control.onContainerClick && _control.onContainerClick($event)">
44+
(click)="_control.onContainerClick($event)">
4545
<div class="mat-mdc-form-field-focus-overlay" *ngIf="!_hasOutline() && !_control.disabled"></div>
4646
<div class="mat-mdc-form-field-flex">
4747
<div *ngIf="_hasOutline()" matFormFieldNotchedOutline

src/material/legacy-form-field/form-field.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="mat-form-field-wrapper">
22
<div class="mat-form-field-flex" #connectionContainer
3-
(click)="_control.onContainerClick && _control.onContainerClick($event)">
3+
(click)="_control.onContainerClick($event)">
44

55
<!-- Outline used for outline appearance. -->
66
<ng-container *ngIf="appearance == 'outline'">
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import ts from 'typescript';
2+
import * as Lint from 'tslint';
3+
4+
const HOOKS_TO_INTERFACES: Record<string, string> = {
5+
'ngOnChanges': 'OnChanges',
6+
'ngOnInit': 'OnInit',
7+
'ngDoCheck': 'DoCheck',
8+
'ngAfterContentInit': 'AfterContentInit',
9+
'ngAfterContentChecked': 'AfterContentChecked',
10+
'ngAfterViewInit': 'AfterViewInit',
11+
'ngAfterViewChecked': 'AfterViewChecked',
12+
'ngOnDestroy': 'OnDestroy',
13+
'ngDoBootstrap': 'DoBootstrap',
14+
};
15+
16+
/**
17+
* Rule that requires classes using Angular lifecycle hooks to implement the appropriate interfaces.
18+
*/
19+
export class Rule extends Lint.Rules.AbstractRule {
20+
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
21+
return this.applyWithWalker(new Walker(sourceFile, this.getOptions()));
22+
}
23+
}
24+
25+
class Walker extends Lint.RuleWalker {
26+
override visitClassDeclaration(node: ts.ClassDeclaration) {
27+
for (const member of node.members) {
28+
if (
29+
!ts.isMethodDeclaration(member) ||
30+
!ts.isIdentifier(member.name) ||
31+
!HOOKS_TO_INTERFACES.hasOwnProperty(member.name.text)
32+
) {
33+
continue;
34+
}
35+
36+
const requiredInterface = HOOKS_TO_INTERFACES[member.name.text];
37+
const hasRequiredInterface = node.heritageClauses?.some(
38+
clause =>
39+
clause.token === ts.SyntaxKind.ImplementsKeyword &&
40+
clause.types.some(
41+
type =>
42+
ts.isExpressionWithTypeArguments(type) &&
43+
ts.isIdentifier(type.expression) &&
44+
type.expression.text === requiredInterface,
45+
),
46+
);
47+
48+
if (!hasRequiredInterface) {
49+
this.addFailureAtNode(
50+
node.name || node,
51+
`Class must implement interface ${requiredInterface}, because it uses Angular lifecycle hook ${member.name.text}`,
52+
);
53+
}
54+
}
55+
56+
return super.visitClassDeclaration(node);
57+
}
58+
}

tools/tslint-rules/memberNamingRule.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Walker extends Lint.RuleWalker {
3737
override visitClassDeclaration(node: ts.ClassDeclaration) {
3838
node.members.forEach(member => {
3939
// Members without a modifier are considered public.
40-
if (!member.modifiers || this._hasModifier(member, ts.SyntaxKind.PublicKeyword)) {
40+
if (this._hasModifier(member, ts.SyntaxKind.PublicKeyword)) {
4141
this._validateMember(member, 'public');
4242
} else if (this._hasModifier(member, ts.SyntaxKind.PrivateKeyword)) {
4343
this._validateMember(member, 'private');
@@ -105,6 +105,6 @@ class Walker extends Lint.RuleWalker {
105105
node: ts.ClassElement | ts.ParameterDeclaration,
106106
targetKind: ts.SyntaxKind,
107107
): boolean {
108-
return !!node.modifiers?.some(({kind}) => kind === targetKind);
108+
return ts.canHaveModifiers(node) && !!node.modifiers?.some(({kind}) => kind === targetKind);
109109
}
110110
}

tslint.json

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
{
22
"extends": ["rxjs-tslint-rules"],
3-
"rulesDirectory": [
4-
"./tools/tslint-rules/",
5-
"node_modules/vrsource-tslint-rules/rules",
6-
"node_modules/codelyzer"
7-
],
3+
"rulesDirectory": ["./tools/tslint-rules/", "node_modules/vrsource-tslint-rules/rules"],
84
"rules": {
95
"ban-types": [true, ["ReadonlyArray<.+>", "Use 'readonly T[]' instead."]],
106
// Disable this flag because of SHA tslint#48b0c597f9257712c7d1f04b55ed0aa60e333f6a
@@ -58,15 +54,6 @@
5854
"await-promise": [true, "PromiseLike"],
5955
"array-type": [true, "array"],
6056

61-
// Codelyzer
62-
"template-banana-in-box": true,
63-
"contextual-lifecycle": true,
64-
"contextual-decorator": true,
65-
"no-output-on-prefix": true,
66-
"prefer-output-readonly": true,
67-
"template-no-negated-async": true,
68-
"use-lifecycle-interface": true,
69-
7057
// RxJS
7158
"rxjs-no-unsafe-takeuntil": true,
7259
"rxjs-no-unsafe-catch": true,
@@ -80,6 +67,7 @@
8067
"no-undecorated-class-with-angular-features": true,
8168
"setters-after-getters": true,
8269
"ng-on-changes-property-access": true,
70+
"lifecycle-hook-interface": true,
8371
"require-breaking-change-version": true,
8472
"no-nested-ternary": true,
8573
"prefer-const-enum": true,

0 commit comments

Comments
 (0)