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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style(aio): enforce strict TypeScript checks #21342

Closed
wants to merge 1 commit into from

Conversation

petebacondarwin
Copy link
Member

@petebacondarwin petebacondarwin commented Jan 5, 2018

Unfortunately the version of @angular/service-worker that we are using (^1.0.0-beta.16)
contains an implicit any which is the only thing preventing the enforcement of noImplicitAny.
This looks like it is fixed in v5+ of the package.

Closes #20646

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

[ ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] angular.io application / infrastructure changes
[ ] Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

[ ] Yes
[ ] No

Other information

@petebacondarwin petebacondarwin added comp: aio action: review The PR is still awaiting reviews from at least one requested reviewer target: patch This PR is targeted for the next patch release labels Jan 5, 2018
@petebacondarwin petebacondarwin added this to REVIEW in docs-infra Jan 5, 2018
@mary-poppins
Copy link

You can preview 78cebb9 at https://pr21342-78cebb9.ngbuilds.io/.

Copy link
Member

@gkalpak gkalpak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM 👍
Just a couple of nits and a linting error.

@@ -1213,9 +1213,9 @@ class TestHttpClient {
data = this.navJson;
} else {
const match = /generated\/docs\/(.+)\.json/.exec(url);
const id = match[1];
const id = match![1]!;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoL
(Maybe move the first ! to the line above?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you insist

Copy link
Member

@gkalpak gkalpak Jan 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't 😇

@@ -31,7 +31,7 @@ describe('SwUpdatesService', () => {
checkInterval = (service as any).checkInterval;
};
const tearDown = () => service.ngOnDestroy();
const run = specFn => () => {
const run = (specFn: Function) => () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come tslint doesn't complain about Function. It usually prefers a specific function signature (e.g. () => void) 😃

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea but I changed it to VoidFunction just to keep you happy.

@@ -193,15 +193,15 @@ export class DocViewerComponent implements DoCheck, OnDestroy {

elem.style.transition = '';
return animationsDisabled
? this.void$.do(() => elem.style[prop] = to)
? this.void$.do(() => (elem.style as any)[prop] = to)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can avoid the as any (here and below), by giving prop a type of keyof CSSStyleDeclaration (which also improves type-safety for the animateProp() function 🎉).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not quite so simple since length and parentRule properties are readonly :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops 😞

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguably, this points out a bug in the code :-) I have put a check for those two properties.

@@ -11,7 +11,7 @@ describe('CustomIconRegistry', () => {
{ name: 'test_icon', svgSource: svgSrc }
];
const registry = new CustomIconRegistry(mockHttp, mockSanitizer, svgIcons);
let svgElement: SVGElement;
let svgElement: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? Doesn't getNamedSvgIcon return an observable of SVGElements?
Is it for comparing with the result of createSvg()? Wouldn't it be more appropriate to "fix" createSvg() instead:

 function createSvg(svgSrc) {
   const div = document.createElement('div');
   div.innerHTML = svgSrc;
-  return div.querySelector('svg');
+  return div.querySelector<SVGElement>('svg')!;
 }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1
I fixed by relaxing the return type of createSvg(svgSrc: string): SVGElement

});

swUpdates.updateActivated.subscribe(() => this.swUpdateActivated = true);
}

// TODO?: ignore if url-without-hash-or-search matches current location?
go(url: string) {
go(url: string|null|undefined) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be preferrable to have go(url?: string|null)? Do we need to explicitly pass undefined?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we do have explicit tests for each of these scenarios: https://github.com/angular/angular/blob/master/aio/src/app/shared/location.service.spec.ts#L272
But looking at the code, we never call with undefined or null so actually let's make it tighter.

search(): { [index: string]: string; } {
const search = {};
search() {
const search: { [index: string]: string|undefined; } = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need the |undefined part?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we do 😱 - perhaps I was being over-zealous!

Actually we have a test for this very scenario: https://github.com/angular/angular/blob/master/aio/src/app/shared/location.service.spec.ts#L339

@@ -80,7 +80,7 @@ export class LocationService {
return search;
}

setSearch(label: string, params: {}) {
setSearch(label: string, params: { [key: string]: string|undefined}) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT, the value type should be string|null|undefined.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so as far as we use this we never pass null, so instead of relaxing the params type I am going to fix the use of double equals below this.

@@ -234,7 +235,7 @@ describe('ScrollSpyService', () => {

it('should remember and emit the last active item to new subscribers', () => {
const items = [{index: 1}, {index: 2}, {index: 3}] as ScrollItem[];
let lastActiveItem: ScrollItem | null;
let lastActiveItem: ScrollItem|null|undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:
|undefined is somewhat confusing imo (and unnecessarily less strict - which is not a concern is tests of course). If it is just for avoiding the "used before being assigned" error, it might be more clear to initialize the value (e.g. let lastActiveItem: ScrollItem|null = null) or use ! when using it (e.g. expect(lastActiveItem!))?

(I understand this stems from TypeScript's current limitation to infer that a value might actual be set (through a synchronous function call) and falls under the "Super Nit" category, so feel free to ignore 😁)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so initially I was concerned that we actually check that this value is null at the end of the test, so if none of the subscription handlers were called then this pass despite not being correct. But I now notice that before we check for it becoming null we check that it is some non-null value, so if none of the handler ran then the first expectation would fail before we get the false positive.

@@ -111,7 +111,7 @@ describe('ScrollService', () => {

const topOfPage = new MockElement();
document.getElementById.and
.callFake(id => id === 'top-of-page' ? topOfPage : null);
.callFake((id:string) => id === 'top-of-page' ? topOfPage : null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space before string. (While you are at it, you can remove the double-space before => 😁)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@@ -5,7 +5,7 @@ export interface SearchResults {

export interface SearchResult {
path: string;
title: string;
title?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OOC, under what circumstances can a search result have no associated title?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never :-) Or at least only if the data is bad.

@IgorMinar
Copy link
Contributor

If I understand Pete's comment correctly, this is blocked on #19795. right?

@petebacondarwin
Copy link
Member Author

@IgorMinar : No, this is not blocked on #19795 but we just can't turn on the final noImplicitAny rule until that lands. Our code is all now compliant with that rule, we just don't have it turned on.

@mary-poppins
Copy link

You can preview d1aa41e at https://pr21342-d1aa41e.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 40a4e68 at https://pr21342-40a4e68.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 124c34e at https://pr21342-124c34e.ngbuilds.io/.

@IgorMinar
Copy link
Contributor

@petebacondarwin I see. that makes sense. thanks

Copy link
Member

@gkalpak gkalpak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (as soon as CI is green 😃)
🎉

@gkalpak gkalpak added the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label Jan 11, 2018
@mary-poppins
Copy link

You can preview d133c0e at https://pr21342-d133c0e.ngbuilds.io/.

@petebacondarwin
Copy link
Member Author

oh I forgot about the e2e scripts

@mary-poppins
Copy link

You can preview 537e4d0 at https://pr21342-537e4d0.ngbuilds.io/.

@gkalpak
Copy link
Member

gkalpak commented Jan 11, 2018

File sizes were affected for some reason 😁
The limits need to be updated.

@petebacondarwin petebacondarwin added action: merge The PR is ready for merge by the caretaker and removed action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews labels Jan 12, 2018
@petebacondarwin petebacondarwin moved this from REVIEW to MERGE in docs-infra Jan 12, 2018
@petebacondarwin petebacondarwin removed the action: review The PR is still awaiting reviews from at least one requested reviewer label Jan 12, 2018
alexeagle pushed a commit that referenced this pull request Jan 12, 2018
@alexeagle alexeagle closed this in c5c6d84 Jan 12, 2018
@gkalpak gkalpak removed this from MERGE in docs-infra Jan 15, 2018
@petebacondarwin petebacondarwin deleted the aio-strict branch January 16, 2018 11:04
leo6104 pushed a commit to leo6104/angular that referenced this pull request Mar 25, 2018
@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 Sep 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enable strictNullChecks mode for aio codebase
5 participants