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
Conversation
You can preview 78cebb9 at https://pr21342-78cebb9.ngbuilds.io/. |
There was a problem hiding this 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.
aio/src/app/app.component.spec.ts
Outdated
@@ -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]!; |
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you insist
There was a problem hiding this comment.
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) => () => { |
There was a problem hiding this comment.
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
) 😃
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 🎉).
There was a problem hiding this comment.
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 :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooops 😞
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 SVGElement
s?
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')!;
}
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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; } = {}; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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}) { |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 😁)
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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 =>
😁)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
aio/src/app/search/interfaces.ts
Outdated
@@ -5,7 +5,7 @@ export interface SearchResults { | |||
|
|||
export interface SearchResult { | |||
path: string; | |||
title: string; | |||
title?: string; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
If I understand Pete's comment correctly, this is blocked on #19795. right? |
@IgorMinar : No, this is not blocked on #19795 but we just can't turn on the final |
d1aa41e
to
40a4e68
Compare
You can preview d1aa41e at https://pr21342-d1aa41e.ngbuilds.io/. |
You can preview 40a4e68 at https://pr21342-40a4e68.ngbuilds.io/. |
40a4e68
to
124c34e
Compare
You can preview 124c34e at https://pr21342-124c34e.ngbuilds.io/. |
@petebacondarwin I see. that makes sense. thanks |
There was a problem hiding this 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 😃)
🎉
124c34e
to
d133c0e
Compare
You can preview d133c0e at https://pr21342-d133c0e.ngbuilds.io/. |
oh I forgot about the e2e scripts |
d133c0e
to
537e4d0
Compare
You can preview 537e4d0 at https://pr21342-537e4d0.ngbuilds.io/. |
File sizes were affected for some reason 😁 |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
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 ofnoImplicitAny
.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?
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information