Skip to content

Commit 6db24ce

Browse files
authored
Remove almost all uses of "any" outside of test code. (lit#741)
* Remove all uses of "any" outside of test code. * Format * Give better types for EventPart * Format * Address review feedback. * Address more review feedback. * Get tests compiling cleanly. * Don't use isThenable function. * Add accidentally deleted check. * Revert isIterable, potentially too expensive. * Use EventListenerOrEventListenerObject instead of reinventing it. * Reformat * Use EventListenerObject type.
1 parent b7dbe20 commit 6db24ce

36 files changed

+499
-399
lines changed

package-lock.json

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"rollup-plugin-filesize": "^4.0.1",
4343
"rollup-plugin-terser": "^1.0.1",
4444
"tslint": "^5.11.0",
45-
"typescript": "^3.1.1",
45+
"typescript": "^3.2.2",
4646
"uglify-es": "^3.3.5",
4747
"wct-mocha": "^1.0.0",
4848
"web-component-tester": "^6.9.0"

src/directives/async-append.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {createMarker, directive, NodePart, Part} from '../lit-html.js';
3333
*/
3434
export const asyncAppend = directive(
3535
<T>(value: AsyncIterable<T>,
36-
mapper?: (v: T, index?: number) => any) => async (part: Part) => {
36+
mapper?: (v: T, index?: number) => unknown) => async (part: Part) => {
3737
if (!(part instanceof NodePart)) {
3838
throw new Error('asyncAppend can only be used in text bindings');
3939
}
@@ -67,7 +67,9 @@ export const asyncAppend = directive(
6767
// we accept a mapper function. This is especially convenient for
6868
// rendering a template for each item.
6969
if (mapper !== undefined) {
70-
v = mapper(v, i);
70+
// This is safe because T must otherwise be treated as unknown by
71+
// the rest of the system.
72+
v = mapper(v, i) as T;
7173
}
7274

7375
// Like with sync iterables, each item induces a Part, so we need

src/directives/async-replace.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {directive, NodePart, Part} from '../lit-html.js';
3333
* value. Useful for generating templates for each item in the iterable.
3434
*/
3535
export const asyncReplace = directive(
36-
<T>(value: AsyncIterable<T>, mapper?: (v: T, index?: number) => any) =>
36+
<T>(value: AsyncIterable<T>, mapper?: (v: T, index?: number) => unknown) =>
3737
async (part: Part) => {
3838
if (!(part instanceof NodePart)) {
3939
throw new Error('asyncReplace can only be used in text bindings');
@@ -70,7 +70,9 @@ export const asyncReplace = directive(
7070
// we accept a mapper function. This is especially convenient for
7171
// rendering a template for each item.
7272
if (mapper !== undefined) {
73-
v = mapper(v, i);
73+
// This is safe because T must otherwise be treated as unknown by
74+
// the rest of the system.
75+
v = mapper(v, i) as T;
7476
}
7577

7678
itemPart.setValue(v);

src/directives/cache.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const templateCaches =
3737
* `
3838
* ```
3939
*/
40-
export const cache = directive((value: any) => (part: Part) => {
40+
export const cache = directive((value: unknown) => (part: Part) => {
4141
if (!(part instanceof NodePart)) {
4242
throw new Error('cache can only be used in text bindings');
4343
}

src/directives/if-defined.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {AttributePart, directive, Part} from '../lit-html.js';
2020
*
2121
* For other part types, this directive is a no-op.
2222
*/
23-
export const ifDefined = directive((value: any) => (part: Part) => {
23+
export const ifDefined = directive((value: unknown) => (part: Part) => {
2424
if (value === undefined && part instanceof AttributePart) {
2525
if (value !== part.value) {
2626
const name = part.committer.name;

src/directives/repeat.ts

+364-325
Large diffs are not rendered by default.

src/directives/style-map.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ export interface StyleInfo {
2222
* Stores the StyleInfo object applied to a given AttributePart.
2323
* Used to unset existing values when a new StyleInfo object is applied.
2424
*/
25-
const styleMapCache = new WeakMap();
25+
const styleMapCache = new WeakMap<AttributePart, StyleInfo>();
2626

2727
/**
2828
* Stores AttributeParts that have had static styles applied (e.g. `height: 0;`
2929
* in style="height: 0; ${styleMap()}"). Static styles are applied only the
3030
* first time the directive is run on a part.
3131
*/
3232
// Note, could be a WeakSet, but prefer not requiring this polyfill.
33-
const styleMapStatics = new WeakMap();
33+
const styleMapStatics = new WeakMap<AttributePart, true>();
3434

3535
/**
3636
* A directive that applies CSS properties to an element.
@@ -70,6 +70,7 @@ export const styleMap = directive((styleInfo: StyleInfo) => (part: Part) => {
7070
for (const name in oldInfo) {
7171
if (!(name in styleInfo)) {
7272
if (name.indexOf('-') === -1) {
73+
// tslint:disable-next-line:no-any
7374
(style as any)[name] = null;
7475
} else {
7576
style.removeProperty(name);
@@ -80,6 +81,7 @@ export const styleMap = directive((styleInfo: StyleInfo) => (part: Part) => {
8081
// Add or update properties
8182
for (const name in styleInfo) {
8283
if (name.indexOf('-') === -1) {
84+
// tslint:disable-next-line:no-any
8385
(style as any)[name] = styleInfo[name];
8486
} else {
8587
style.setProperty(name, styleInfo[name]);

src/directives/unsafe-html.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {isPrimitive} from '../lib/parts.js';
1616
import {directive, NodePart, Part} from '../lit-html.js';
1717

1818
interface PreviousValue {
19-
value: any;
19+
value: unknown;
2020
fragment: DocumentFragment;
2121
}
2222

@@ -34,7 +34,7 @@ const previousValues = new WeakMap<NodePart, PreviousValue>();
3434
* sanitized or escaped, as it may lead to cross-site-scripting
3535
* vulnerabilities.
3636
*/
37-
export const unsafeHTML = directive((value: any) => (part: Part): void => {
37+
export const unsafeHTML = directive((value: unknown) => (part: Part): void => {
3838
if (!(part instanceof NodePart)) {
3939
throw new Error('unsafeHTML can only be used in text bindings');
4040
}
@@ -47,7 +47,7 @@ export const unsafeHTML = directive((value: any) => (part: Part): void => {
4747
}
4848

4949
const template = document.createElement('template');
50-
template.innerHTML = value;
50+
template.innerHTML = value as string; // innerHTML casts to string internally
5151
const fragment = document.importNode(template.content, true);
5252
part.setValue(fragment);
5353
previousValues.set(part, {value, fragment});

src/directives/until.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const _state = new WeakMap<Part, AsyncState>();
4646
* const content = fetch('./content.txt').then(r => r.text());
4747
* html`${until(content, html`<span>Loading...</span>`)}`
4848
*/
49-
export const until = directive((...args: any[]) => (part: Part) => {
49+
export const until = directive((...args: unknown[]) => (part: Part) => {
5050
let state = _state.get(part)!;
5151
if (state === undefined) {
5252
state = {
@@ -66,7 +66,8 @@ export const until = directive((...args: any[]) => (part: Part) => {
6666
const value = args[i];
6767

6868
// Render non-Promise values immediately
69-
if (isPrimitive(value) || typeof value.then !== 'function') {
69+
if (isPrimitive(value) ||
70+
typeof (value as {then?: unknown}).then !== 'function') {
7071
part.setValue(value);
7172
state.lastRenderedIndex = i;
7273
// Since a lower-priority value will never overwrite a higher-priority
@@ -76,7 +77,8 @@ export const until = directive((...args: any[]) => (part: Part) => {
7677

7778
// If this is a Promise we've already handled, skip it.
7879
if (state.lastRenderedIndex !== undefined &&
79-
typeof value.then === 'function' && value === previousValues[i]) {
80+
typeof (value as {then?: unknown}).then === 'function' &&
81+
value === previousValues[i]) {
8082
continue;
8183
}
8284

src/lib/directive.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818

1919
import {Part} from './part.js';
2020

21-
const directives = new WeakMap<any, Boolean>();
21+
const directives = new WeakMap<object, true>();
22+
23+
// tslint:disable-next-line:no-any
24+
export type DirectiveFactory = (...args: any[]) => object;
2225

2326
export type DirectiveFn = (part: Part) => void;
2427

@@ -42,12 +45,14 @@ export type DirectiveFn = (part: Part) => void;
4245
* });
4346
* ```
4447
*/
45-
export const directive = <F extends Function>(f: F): F =>
46-
((...args: any[]) => {
48+
// tslint:disable-next-line:no-any
49+
export const directive = <F extends DirectiveFactory>(f: F): F =>
50+
((...args: unknown[]) => {
4751
const d = f(...args);
4852
directives.set(d, true);
4953
return d;
50-
}) as unknown as F;
54+
}) as F;
5155

52-
export const isDirective = (o: any) =>
53-
typeof o === 'function' && directives.has(o);
56+
export const isDirective = (o: unknown): o is DirectiveFn => {
57+
return typeof o === 'function' && directives.has(o);
58+
};

src/lib/dom.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@
1616
* @module lit-html
1717
*/
1818

19+
interface MaybePolyfilledCe extends CustomElementRegistry {
20+
polyfillWrapFlushCallback?: object;
21+
}
22+
1923
/**
2024
* True if the custom elements polyfill is in use.
2125
*/
2226
export const isCEPolyfill = window.customElements !== undefined &&
23-
(window.customElements as any).polyfillWrapFlushCallback !== undefined;
27+
(window.customElements as MaybePolyfilledCe).polyfillWrapFlushCallback !==
28+
undefined;
2429

2530
/**
2631
* Reparents nodes, starting from `startNode` (inclusive) to `endNode`

src/lib/modify-template.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function removeNodesFromTemplate(
4040
template: Template, nodesToRemove: Set<Node>) {
4141
const {element: {content}, parts} = template;
4242
const walker =
43-
document.createTreeWalker(content, walkerNodeFilter, null as any, false);
43+
document.createTreeWalker(content, walkerNodeFilter, null, false);
4444
let partIndex = nextActiveIndexInTemplateParts(parts);
4545
let part = parts[partIndex];
4646
let nodeIndex = -1;
@@ -80,8 +80,7 @@ export function removeNodesFromTemplate(
8080

8181
const countNodes = (node: Node) => {
8282
let count = (node.nodeType === 11 /* Node.DOCUMENT_FRAGMENT_NODE */) ? 0 : 1;
83-
const walker =
84-
document.createTreeWalker(node, walkerNodeFilter, null as any, false);
83+
const walker = document.createTreeWalker(node, walkerNodeFilter, null, false);
8584
while (walker.nextNode()) {
8685
count++;
8786
}
@@ -114,7 +113,7 @@ export function insertNodeIntoTemplate(
114113
return;
115114
}
116115
const walker =
117-
document.createTreeWalker(content, walkerNodeFilter, null as any, false);
116+
document.createTreeWalker(content, walkerNodeFilter, null, false);
118117
let partIndex = nextActiveIndexInTemplateParts(parts);
119118
let insertCount = 0;
120119
let walkerIndex = -1;

src/lib/part.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
* by lit-html.
2222
*/
2323
export interface Part {
24-
value: any;
24+
value: unknown;
2525

2626
/**
2727
* Sets the current part value, but does not write it to the DOM.
2828
* @param value The value that will be committed.
2929
*/
30-
setValue(value: any): void;
30+
setValue(value: unknown): void;
3131

3232
/**
3333
* Commits the current part value, cause it to actually be written to the DOM.
@@ -39,7 +39,7 @@ export interface Part {
3939
* A sentinel value that signals that a value was handled by a directive and
4040
* should not be written to the DOM.
4141
*/
42-
export const noChange = {};
42+
export const noChange: object = {};
4343

4444
/**
4545
* A sentinel value that signals a NodePart to fully clear its content.

0 commit comments

Comments
 (0)