Skip to content

Commit 4042731

Browse files
committed
Simplify expectations
1 parent 8ab7004 commit 4042731

File tree

5 files changed

+71
-204
lines changed

5 files changed

+71
-204
lines changed

spec/common/metaprogramming.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,6 @@
2020
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
// SOFTWARE.
2222

23-
export type SameType<A, B> = A extends B ? (B extends A ? true : never) : never;
24-
export type IsNever<A> = never extends A ? true : never;
25-
26-
// Sanity check: uncommenting this line should cause a compilation error
27-
// const assertion: SameType<number, string> = true;
28-
29-
// TypeScript will fail to compile with an unused variable and our TS settings.
30-
// Rather than turn off unused var checks globally or all errors in this file,
31-
// we'll use a stupid function to silence the compiler.
32-
export function use<T>(t: T) {}
23+
// This method will fail to compile if value is not of the explicit parameter type.
24+
export function expectType<Type>(value: Type) {}
25+
export function expectNever<Type extends never>() {}

spec/common/params.spec.ts

Lines changed: 32 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -17,102 +17,83 @@
1717
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE ignoreUnusedWarning OR OTHER DEALINGS IN THE
2121
// SOFTWARE.
2222

2323
import { Extract, ParamsOf, Split } from '../../src/common/params';
24-
import { IsNever, SameType, use } from './metaprogramming';
24+
import { expectNever, expectType } from './metaprogramming';
2525

2626
describe('Params namespace', () => {
2727
describe('Split', () => {
28+
// Note the subtle difference in the first two cases:
29+
// if passed a string (instead of a string literal) then split returns a
30+
// string[], which means "any number of elements as long as they are a string"
31+
// but if passed a literal string "" then split returns [] which means "a
32+
// tuple of zero elements".
33+
2834
it('handles generic strings', () => {
29-
// @ts-ignore
30-
const assertion: SameType<Split<string, '/'>, string[]> = true;
31-
use(assertion);
35+
expectType<Split<string, '/'>>([] as string[]);
3236
});
3337

34-
it('handles literal strings with one component', () => {
35-
const assertion: SameType<Split<'a', '/'>, ['a']> = true;
36-
use(assertion);
38+
it('handles empty strings', () => {
39+
expectType<Split<'', '/'>>([]);
3740
});
3841

39-
it('handles literal strings with more than one component', () => {
40-
const assertion: SameType<Split<'a/b/c', '/'>, ['a', 'b', 'c']> = true;
41-
use(assertion);
42+
it('handles just a slash', () => {
43+
expectType<Split<'/', '/'>>([]);
4244
});
4345

44-
it('strips leading slashes', () => {
45-
const assertion: SameType<Split<'/a/b/c', '/'>, ['a', 'b', 'c']> = true;
46-
use(assertion);
46+
it('handles literal strings with one component', () => {
47+
expectType<Split<'a', '/'>>(['a']);
4748
});
4849

49-
it('handles empty strings', () => {
50-
const assertion: SameType<Split<'', '/'>, []> = true;
51-
use(assertion);
50+
it('handles literal strings with more than one component', () => {
51+
expectType<Split<'a/b/c', '/'>>(['a', 'b', 'c']);
5252
});
5353

54-
it('handles just a slash', () => {
55-
const assertion: SameType<Split<'/', '/'>, []> = true;
56-
use(assertion);
54+
it('strips leading slashes', () => {
55+
expectType<Split<'/a/b/c', '/'>>(['a', 'b', 'c']);
5756
});
5857
});
5958

6059
describe('Extract', () => {
6160
it('extracts nothing from strings without params', () => {
62-
const assertion: IsNever<Extract<'uid'>> = true;
63-
use(assertion);
61+
expectNever<Extract<'uid'>>();
6462
});
6563

6664
it('extracts {segment} captures', () => {
67-
const assertion: SameType<Extract<'{uid}'>, 'uid'> = true;
68-
use(assertion);
65+
expectType<Extract<'{uid}'>>('uid');
6966
});
7067

7168
it('extracts {segment=*} captures', () => {
72-
const assertion: SameType<Extract<'{uid=*}'>, 'uid'> = true;
73-
use(assertion);
69+
expectType<Extract<'{uid=*}'>>('uid');
7470
});
7571

7672
it('extracts {segment=**} captures', () => {
77-
const assertion: SameType<Extract<'{uid=**}'>, 'uid'> = true;
78-
use(assertion);
73+
expectType<Extract<'{uid=**}'>>('uid');
7974
});
8075
});
8176

8277
describe('ParamsOf', () => {
8378
it('falls back to Record<string, string> without better type info', () => {
84-
const assertion: SameType<
85-
ParamsOf<string>,
86-
Record<string, string>
87-
> = true;
88-
use(assertion);
79+
expectType<ParamsOf<string>>({} as Record<string, string>);
8980
});
9081

9182
it('is the empty object when there are no params', () => {
92-
const assertion: SameType<
93-
ParamsOf<'a/b/c'>,
94-
Record<string, never>
95-
> = true;
96-
use(assertion);
83+
expectType<ParamsOf<string>>({} as Record<string, never>);
9784
});
9885

9986
it('extracts a single param', () => {
100-
const assertion: SameType<
101-
ParamsOf<'users/{uid}'>,
102-
{ uid: string }
103-
> = true;
104-
use(assertion);
87+
expectType<ParamsOf<'ignoreUnusedWarningrs/{uid}'>>({
88+
uid: 'uid',
89+
} as const);
10590
});
10691

10792
it('extracts multiple params', () => {
108-
const assertion: SameType<
109-
ParamsOf<'users/{uid}/logs/{log=**}'>,
110-
{
111-
uid: string;
112-
log: string;
113-
}
114-
> = true;
115-
use(assertion);
93+
expectType<ParamsOf<'ignoreUnusedWarningrs/{uid}/logs/{log=**}'>>({
94+
uid: 'hello',
95+
log: 'world',
96+
} as const);
11697
});
11798
});
11899
});

spec/v1/providers/database.spec.ts

Lines changed: 18 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import * as config from '../../../src/common/config';
2626
import { applyChange } from '../../../src/common/utilities/utils';
2727
import * as functions from '../../../src/v1';
2828
import * as database from '../../../src/v1/providers/database';
29-
import { SameType, use } from '../../common/metaprogramming';
29+
import { expectType } from '../../common/metaprogramming';
3030

3131
describe('Database Functions', () => {
3232
describe('DatabaseBuilder', () => {
@@ -124,30 +124,13 @@ describe('Database Functions', () => {
124124

125125
it('Should have params of the correct type', () => {
126126
database.ref('foo').onWrite((event, context) => {
127-
const assertion: SameType<
128-
typeof context.params,
129-
Record<string, never>
130-
> = true;
131-
use(assertion);
127+
expectType<Record<string, never>>(context.params);
132128
});
133129
database.ref('foo/{bar}').onWrite((event, context) => {
134-
const assertion: SameType<
135-
typeof context.params,
136-
{
137-
bar: string;
138-
}
139-
> = true;
140-
use(assertion);
130+
expectType<{ bar: string }>(context.params);
141131
});
142132
database.ref('foo/{bar}/{baz}').onWrite((event, context) => {
143-
const assertion: SameType<
144-
typeof context.params,
145-
{
146-
bar: string;
147-
baz: string;
148-
}
149-
> = true;
150-
use(assertion);
133+
expectType<{ bar: string; baz: string }>(context.params);
151134
});
152135
});
153136
});
@@ -201,30 +184,13 @@ describe('Database Functions', () => {
201184

202185
it('Should have params of the correct type', () => {
203186
database.ref('foo').onCreate((event, context) => {
204-
const assertion: SameType<
205-
typeof context.params,
206-
Record<string, never>
207-
> = true;
208-
use(assertion);
187+
expectType<Record<string, never>>(context.params);
209188
});
210189
database.ref('foo/{bar}').onCreate((event, context) => {
211-
const assertion: SameType<
212-
typeof context.params,
213-
{
214-
bar: string;
215-
}
216-
> = true;
217-
use(assertion);
190+
expectType<{ bar: string }>(context.params);
218191
});
219192
database.ref('foo/{bar}/{baz}').onCreate((event, context) => {
220-
const assertion: SameType<
221-
typeof context.params,
222-
{
223-
bar: string;
224-
baz: string;
225-
}
226-
> = true;
227-
use(assertion);
193+
expectType<{ bar: string; baz: string }>(context.params);
228194
});
229195
});
230196
});
@@ -278,30 +244,13 @@ describe('Database Functions', () => {
278244

279245
it('Should have params of the correct type', () => {
280246
database.ref('foo').onUpdate((event, context) => {
281-
const assertion: SameType<
282-
typeof context.params,
283-
Record<string, never>
284-
> = true;
285-
use(assertion);
247+
expectType<Record<string, never>>(context.params);
286248
});
287249
database.ref('foo/{bar}').onUpdate((event, context) => {
288-
const assertion: SameType<
289-
typeof context.params,
290-
{
291-
bar: string;
292-
}
293-
> = true;
294-
use(assertion);
250+
expectType<{ bar: string }>(context.params);
295251
});
296252
database.ref('foo/{bar}/{baz}').onUpdate((event, context) => {
297-
const assertion: SameType<
298-
typeof context.params,
299-
{
300-
bar: string;
301-
baz: string;
302-
}
303-
> = true;
304-
use(assertion);
253+
expectType<{ bar: string; baz: string }>(context.params);
305254
});
306255
});
307256
});
@@ -355,31 +304,14 @@ describe('Database Functions', () => {
355304
});
356305

357306
it('Should have params of the correct type', () => {
358-
database.ref('foo').onUpdate((event, context) => {
359-
const assertion: SameType<
360-
typeof context.params,
361-
Record<string, never>
362-
> = true;
363-
use(assertion);
364-
});
365-
database.ref('foo/{bar}').onUpdate((event, context) => {
366-
const assertion: SameType<
367-
typeof context.params,
368-
{
369-
bar: string;
370-
}
371-
> = true;
372-
use(assertion);
373-
});
374-
database.ref('foo/{bar}/{baz}').onUpdate((event, context) => {
375-
const assertion: SameType<
376-
typeof context.params,
377-
{
378-
bar: string;
379-
baz: string;
380-
}
381-
> = true;
382-
use(assertion);
307+
database.ref('foo').onDelete((event, context) => {
308+
expectType<Record<string, never>>(context.params);
309+
});
310+
database.ref('foo/{bar}').onDelete((event, context) => {
311+
expectType<{ bar: string }>(context.params);
312+
});
313+
database.ref('foo/{bar}/{baz}').onDelete((event, context) => {
314+
expectType<{ bar: string; baz: string }>(context.params);
383315
});
384316
});
385317
});

spec/v1/providers/firestore.spec.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { Timestamp } from 'firebase-admin/firestore';
2525

2626
import * as functions from '../../../src/v1';
2727
import * as firestore from '../../../src/v1/providers/firestore';
28-
import { SameType, use } from '../../common/metaprogramming';
28+
import { expectType } from '../../common/metaprogramming';
2929

3030
describe('Firestore Functions', () => {
3131
function constructValue(fields: any) {
@@ -119,9 +119,7 @@ describe('Firestore Functions', () => {
119119
const cloudFunction = firestore
120120
.document('users/{uid}')
121121
.onWrite((snap, context) => {
122-
const assertion: SameType<typeof context.params, { uid: string }> =
123-
true;
124-
use(assertion);
122+
expectType<{ uid: string }>(context.params);
125123
});
126124

127125
expect(cloudFunction.__endpoint).to.deep.equal(
@@ -136,9 +134,7 @@ describe('Firestore Functions', () => {
136134
.namespace('v2')
137135
.document('users/{uid}')
138136
.onWrite((snap, context) => {
139-
const assertion: SameType<typeof context.params, { uid: string }> =
140-
true;
141-
use(assertion);
137+
expectType<{ uid: string }>(context.params);
142138
});
143139

144140
expect(cloudFunction.__endpoint).to.deep.equal(
@@ -166,9 +162,7 @@ describe('Firestore Functions', () => {
166162
.namespace('v2')
167163
.document('users/{uid}')
168164
.onWrite((snap, context) => {
169-
const assertion: SameType<typeof context.params, { uid: string }> =
170-
true;
171-
use(assertion);
165+
expectType<{ uid: string }>(context.params);
172166
});
173167

174168
expect(cloudFunction.__endpoint).to.deep.equal(
@@ -185,11 +179,7 @@ describe('Firestore Functions', () => {
185179
})
186180
.firestore.document('doc')
187181
.onCreate((snap, context) => {
188-
const assertion: SameType<
189-
typeof context.params,
190-
Record<string, never>
191-
> = true;
192-
use(assertion);
182+
expectType<Record<string, string>>(context.params);
193183
});
194184

195185
expect(fn.__endpoint.region).to.deep.equal(['us-east1']);

0 commit comments

Comments
 (0)