Skip to content

Commit 5eea608

Browse files
committed
Turn assertions into type guards
Update the `deepEqual`, `like`, `false`, `true` and `is` assertions so they can be used as type guards. Fixes #2456. Change the `deepEqual`, `like` and `is` assertions so the actual and expected parameters can be typed separately. Fixes #2580.
1 parent 72a4e2f commit 5eea608

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

index.d.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ export interface DeepEqualAssertion {
150150
* Assert that `actual` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
151151
* `expected`, returning a boolean indicating whether the assertion passed.
152152
*/
153-
<ValueType = any>(actual: ValueType, expected: ValueType, message?: string): boolean;
153+
<Actual, Expected extends Actual>(actual: Actual, expected: Expected, message?: string): actual is Expected;
154154

155155
/** Skip this assertion. */
156156
skip(actual: any, expected: any, message?: string): void;
@@ -160,7 +160,7 @@ export interface LikeAssertion {
160160
/**
161161
* Assert that `value` is like `selector`, returning a boolean indicating whether the assertion passed.
162162
*/
163-
(value: any, selector: Record<string, any>, message?: string): boolean;
163+
<Expected extends Record<string, any>>(value: any, selector: Expected, message?: string): value is Expected;
164164

165165
/** Skip this assertion. */
166166
skip(value: any, selector: any, message?: string): void;
@@ -178,7 +178,7 @@ export interface FalseAssertion {
178178
/**
179179
* Assert that `actual` is strictly false, returning a boolean indicating whether the assertion passed.
180180
*/
181-
(actual: any, message?: string): boolean;
181+
(actual: any, message?: string): actual is false;
182182

183183
/** Skip this assertion. */
184184
skip(actual: any, message?: string): void;
@@ -201,7 +201,7 @@ export interface IsAssertion {
201201
* value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`,
202202
* returning a boolean indicating whether the assertion passed.
203203
*/
204-
<ValueType = any>(actual: ValueType, expected: ValueType, message?: string): boolean;
204+
<Actual, Expected extends Actual>(actual: Actual, expected: Expected, message?: string): actual is Expected;
205205

206206
/** Skip this assertion. */
207207
skip(actual: any, expected: any, message?: string): void;
@@ -213,7 +213,7 @@ export interface NotAssertion {
213213
* value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`,
214214
* returning a boolean indicating whether the assertion passed.
215215
*/
216-
<ValueType = any>(actual: ValueType, expected: ValueType, message?: string): boolean;
216+
<Actual, Expected>(actual: Actual, expected: Expected, message?: string): boolean;
217217

218218
/** Skip this assertion. */
219219
skip(actual: any, expected: any, message?: string): void;
@@ -224,7 +224,7 @@ export interface NotDeepEqualAssertion {
224224
* Assert that `actual` is not [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
225225
* `expected`, returning a boolean indicating whether the assertion passed.
226226
*/
227-
<ValueType = any>(actual: ValueType, expected: ValueType, message?: string): boolean;
227+
<Actual, Expected>(actual: Actual, expected: Expected, message?: string): boolean;
228228

229229
/** Skip this assertion. */
230230
skip(actual: any, expected: any, message?: string): void;
@@ -334,7 +334,7 @@ export interface TrueAssertion {
334334
/**
335335
* Assert that `actual` is strictly true, returning a boolean indicating whether the assertion passed.
336336
*/
337-
(actual: any, message?: string): boolean;
337+
(actual: any, message?: string): actual is true;
338338

339339
/** Skip this assertion. */
340340
skip(actual: any, message?: string): void;

test-d/assertions-as-type-guards.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {expectType} from 'tsd';
2+
import test from '..';
3+
4+
type Expected = {foo: 'bar'};
5+
const expected: Expected = {foo: 'bar'};
6+
7+
test('deepEqual', t => {
8+
const actual: unknown = {};
9+
if (t.deepEqual(actual, expected)) {
10+
expectType<Expected>(actual);
11+
}
12+
});
13+
14+
test('like', t => {
15+
const actual: unknown = {};
16+
if (t.like(actual, expected)) {
17+
expectType<Expected>(actual);
18+
}
19+
});
20+
21+
test('is', t => {
22+
const actual: unknown = 2;
23+
if (t.is(actual, 3 as const)) {
24+
expectType<3>(actual);
25+
}
26+
});
27+
28+
test('false', t => {
29+
const actual: unknown = true;
30+
if (t.false(actual)) {
31+
expectType<false>(actual);
32+
}
33+
});
34+
35+
test('true', t => {
36+
const actual: unknown = false;
37+
if (t.true(actual)) {
38+
expectType<true>(actual);
39+
}
40+
});

0 commit comments

Comments
 (0)