Skip to content

Commit 22ed571

Browse files
author
Greg Soltis
authored
Enable strict function types (#1082)
* Strict * More strictness * [AUTOMATED]: Prettier Code Styling * Lint and cleanup * Use Unknown type
1 parent 2dab48d commit 22ed571

11 files changed

+52
-34
lines changed

packages/firestore/src/local/indexeddb_mutation_queue.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ export class IndexedDbMutationQueue implements MutationQueue {
200200
getLastStreamToken(
201201
transaction: PersistenceTransaction
202202
): PersistencePromise<ProtoByteString> {
203-
return PersistencePromise.resolve(this.metadata.lastStreamToken);
203+
return PersistencePromise.resolve<ProtoByteString>(
204+
this.metadata.lastStreamToken
205+
);
204206
}
205207

206208
setLastStreamToken(

packages/firestore/src/local/persistence_promise.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export class PersistencePromise<T> {
157157
static resolve(): PersistencePromise<void>;
158158
static resolve<R>(result: R): PersistencePromise<R>;
159159
static resolve<R>(result?: R): PersistencePromise<R | void> {
160-
return new PersistencePromise<R>((resolve, reject) => {
160+
return new PersistencePromise<R | void>((resolve, reject) => {
161161
resolve(result);
162162
});
163163
}

packages/firestore/src/local/simple_db.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { debug } from '../util/log';
1919
import { AnyDuringMigration } from '../util/misc';
2020
import { PersistencePromise } from './persistence_promise';
2121
import { SCHEMA_VERSION } from './indexeddb_schema';
22+
import { AnyJs } from '../util/misc';
2223
import { Deferred } from '../util/promise';
2324
import { Code, FirestoreError } from '../util/error';
2425

@@ -71,7 +72,7 @@ export class SimpleDb {
7172
);
7273
};
7374

74-
request.onerror = (event: ErrorEvent) => {
75+
request.onerror = (event: Event) => {
7576
reject((event.target as IDBOpenDBRequest).error);
7677
};
7778

@@ -147,7 +148,7 @@ export class SimpleDb {
147148
}
148149

149150
/** Helper to get a typed SimpleDbStore from a transaction. */
150-
static getStore<KeyType extends IDBValidKey, ValueType>(
151+
static getStore<KeyType extends IDBValidKey, ValueType extends AnyJs>(
151152
txn: SimpleDbTransaction,
152153
store: string
153154
): SimpleDbStore<KeyType, ValueType> {
@@ -319,7 +320,7 @@ export class SimpleDbTransaction {
319320
* Note that we can't actually enforce that the KeyType and ValueType are
320321
* correct, but they allow type safety through the rest of the consuming code.
321322
*/
322-
store<KeyType extends IDBValidKey, ValueType>(
323+
store<KeyType extends IDBValidKey, ValueType extends AnyJs>(
323324
storeName: string
324325
): SimpleDbStore<KeyType, ValueType> {
325326
const store = this.transaction.objectStore(storeName);
@@ -338,7 +339,10 @@ export class SimpleDbTransaction {
338339
* 3) Provides a higher-level API to avoid needing to do excessive wrapping of
339340
* intermediate IndexedDB types (IDBCursorWithValue, etc.)
340341
*/
341-
export class SimpleDbStore<KeyType extends IDBValidKey, ValueType> {
342+
export class SimpleDbStore<
343+
KeyType extends IDBValidKey,
344+
ValueType extends AnyJs
345+
> {
342346
constructor(private store: IDBObjectStore) {}
343347

344348
/**

packages/firestore/src/platform_node/grpc_connection.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ export class GrpcConnection implements Connection {
210210
const grpcStream = rpc();
211211

212212
let closed = false;
213-
let close: (err?: Error) => void;
213+
let close: (err?: FirestoreError) => void;
214214

215215
const stream = new StreamBridge<Req, Resp>({
216216
sendFn: (msg: Req) => {

packages/firestore/src/util/async_queue.ts

+12-12
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import { assert, fail } from './assert';
1818
import * as log from './log';
19-
import { AnyJs } from './misc';
19+
import { Unknown } from './misc';
2020
import { Deferred, CancelablePromise } from './promise';
2121
import { Code, FirestoreError } from './error';
2222

@@ -60,7 +60,7 @@ export enum TimerId {
6060
*
6161
* Supports cancellation (via cancel()) and early execution (via skipDelay()).
6262
*/
63-
class DelayedOperation<T> implements CancelablePromise<T> {
63+
class DelayedOperation<T extends Unknown> implements CancelablePromise<T> {
6464
// handle for use with clearTimeout(), or null if the operation has been
6565
// executed or canceled already.
6666
private timerHandle: TimerHandle | null;
@@ -94,13 +94,13 @@ class DelayedOperation<T> implements CancelablePromise<T> {
9494
* PORTING NOTE: This exists to prevent making removeDelayedOperation() and
9595
* the DelayedOperation class public.
9696
*/
97-
static createAndSchedule<T>(
97+
static createAndSchedule<R extends Unknown>(
9898
asyncQueue: AsyncQueue,
9999
timerId: TimerId,
100100
delayMs: number,
101-
op: () => Promise<T>,
102-
removalCallback: (op: DelayedOperation<T>) => void
103-
): DelayedOperation<T> {
101+
op: () => Promise<R>,
102+
removalCallback: (op: DelayedOperation<R>) => void
103+
): DelayedOperation<R> {
104104
const targetTime = Date.now() + delayMs;
105105
const delayedOp = new DelayedOperation(
106106
asyncQueue,
@@ -177,11 +177,11 @@ class DelayedOperation<T> implements CancelablePromise<T> {
177177

178178
export class AsyncQueue {
179179
// The last promise in the queue.
180-
private tail: Promise<AnyJs | void> = Promise.resolve();
180+
private tail: Promise<Unknown> = Promise.resolve();
181181

182182
// Operations scheduled to be queued in the future. Operations are
183183
// automatically removed after they are run or canceled.
184-
private delayedOperations: Array<DelayedOperation<AnyJs>> = [];
184+
private delayedOperations: Array<DelayedOperation<Unknown>> = [];
185185

186186
// visible for testing
187187
failure: Error;
@@ -194,7 +194,7 @@ export class AsyncQueue {
194194
* Adds a new operation to the queue. Returns a promise that will be resolved
195195
* when the promise returned by the new operation is (with its value).
196196
*/
197-
enqueue<T>(op: () => Promise<T>): Promise<T> {
197+
enqueue<T extends Unknown>(op: () => Promise<T>): Promise<T> {
198198
this.verifyNotFailed();
199199
const newTail = this.tail.then(() => {
200200
this.operationInProgress = true;
@@ -233,7 +233,7 @@ export class AsyncQueue {
233233
* `delayMs` has elapsed. The returned CancelablePromise can be used to cancel
234234
* the operation prior to its running.
235235
*/
236-
enqueueAfterDelay<T>(
236+
enqueueAfterDelay<T extends Unknown>(
237237
timerId: TimerId,
238238
delayMs: number,
239239
op: () => Promise<T>
@@ -247,7 +247,7 @@ export class AsyncQueue {
247247
`Attempted to schedule multiple operations with timer id ${timerId}.`
248248
);
249249

250-
const delayedOp = DelayedOperation.createAndSchedule(
250+
const delayedOp = DelayedOperation.createAndSchedule<Unknown>(
251251
this,
252252
timerId,
253253
delayMs,
@@ -329,7 +329,7 @@ export class AsyncQueue {
329329
}
330330

331331
/** Called once a DelayedOperation is run or canceled. */
332-
private removeDelayedOperation<T>(op: DelayedOperation<T>): void {
332+
private removeDelayedOperation(op: DelayedOperation<Unknown>): void {
333333
// NOTE: indexOf / slice are O(n), but delayedOperations is expected to be small.
334334
const index = this.delayedOperations.indexOf(op);
335335
assert(index >= 0, 'Delayed operation not found.');

packages/firestore/src/util/misc.ts

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ export type EventHandler<E> = (value: E) => void;
2525
*/
2626
export type AnyJs = null | undefined | boolean | number | string | object;
2727

28+
/**
29+
* `Unknown` is a stand-in for Typescript 3's `unknown` type. It is similar to
30+
* `any` but forces code to check types before performing operations on a value
31+
* of type `Unknown`. See: https://blogs.msdn.microsoft.com/typescript/2018/07/30/announcing-typescript-3-0/#the-unknown-type
32+
*/
33+
export type Unknown = null | undefined | {} | void;
34+
2835
// TODO(b/66916745): AnyDuringMigration was used to suppress type check failures
2936
// that were found during the upgrade to TypeScript 2.4. They need to be audited
3037
// and fixed.

packages/firestore/test/unit/local/indexeddb_schema.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function withDb(
5353
request.onsuccess = (event: Event) => {
5454
resolve((event.target as IDBOpenDBRequest).result);
5555
};
56-
request.onerror = (event: ErrorEvent) => {
56+
request.onerror = (event: Event) => {
5757
reject((event.target as IDBOpenDBRequest).error);
5858
};
5959
})

packages/firestore/test/unit/local/persistence_promise.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ describe('PersistencePromise', () => {
198198
})
199199
);
200200
updates.push(
201-
async(1).next(x => {
201+
async(1).next<void>(x => {
202202
throw error;
203203
})
204204
);

packages/firestore/test/unit/specs/spec_test_runner.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ import {
8787
path,
8888
setMutation,
8989
TestSnapshotVersion,
90-
version
90+
version,
91+
expectFirestoreError
9192
} from '../../util/helpers';
9293

9394
class MockConnection implements Connection {
@@ -308,9 +309,9 @@ class EventAggregator implements Observer<ViewSnapshot> {
308309
});
309310
}
310311

311-
error(error: FirestoreError): void {
312-
expect(error.code).to.exist;
313-
this.pushEvent({ query: this.query, error });
312+
error(error: Error): void {
313+
expectFirestoreError(error);
314+
this.pushEvent({ query: this.query, error: error as FirestoreError });
314315
}
315316
}
316317

@@ -913,8 +914,7 @@ abstract class TestRunner {
913914
const expectedQuery = this.parseQuery(expected.query);
914915
expect(actual.query).to.deep.equal(expectedQuery);
915916
if (expected.errorCode) {
916-
// TODO(dimond): better matcher
917-
expect(actual.error instanceof Error).to.equal(true);
917+
expectFirestoreError(actual.error);
918918
} else {
919919
const expectedChanges: DocumentViewChange[] = [];
920920
if (expected.removed) {

packages/firestore/test/util/helpers.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -555,9 +555,9 @@ export function expectEqualArrays(
555555
* Checks that an ordered array of elements yields the correct pair-wise
556556
* comparison result for the supplied comparator
557557
*/
558-
export function expectCorrectComparisons(
559-
array: AnyJs[],
560-
comp: (left: AnyJs, right: AnyJs) => number
558+
export function expectCorrectComparisons<T extends AnyJs>(
559+
array: T[],
560+
comp: (left: T, right: T) => number
561561
): void {
562562
for (let i = 0; i < array.length; i++) {
563563
for (let j = 0; j < array.length; j++) {
@@ -584,9 +584,9 @@ export function expectCorrectComparisons(
584584
* returns the same as comparing the indexes of the "equality groups"
585585
* (0 for items in the same group).
586586
*/
587-
export function expectCorrectComparisonGroups(
588-
groups: AnyJs[][],
589-
comp: (left: AnyJs, right: AnyJs) => number
587+
export function expectCorrectComparisonGroups<T extends AnyJs>(
588+
groups: T[][],
589+
comp: (left: T, right: T) => number
590590
): void {
591591
for (let i = 0; i < groups.length; i++) {
592592
for (const left of groups[i]) {
@@ -674,3 +674,7 @@ export function size(obj: JsonObject<AnyJs>): number {
674674
forEach(obj, () => c++);
675675
return c;
676676
}
677+
678+
export function expectFirestoreError(err: Error): void {
679+
expect(err.name).to.equal('FirebaseError');
680+
}

packages/firestore/tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"extends": "../../config/tsconfig.base.json",
33
"compilerOptions": {
4-
"outDir": "dist"
4+
"outDir": "dist",
5+
"strictFunctionTypes": true
56
},
67
"exclude": [
78
"dist/**/*"

0 commit comments

Comments
 (0)