denoland / denoland/std

[`@std/expect`] Add optional generics to matchers like `toStrictEqual` to make it easier to type expected values

Open
#6,398 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
3.6k
Forks
681
PR merge metrics
No merged PRs in 30d

Description

**Is your feature request related to a problem? Please describe.**

Currently when using matchers like `toStrictEqual` (and many others), the type of the argument is `unknown`, which can potentially make it (slightly) slower to make tests correct and ensure type safety. Compared to using `assertStrictEquals` from `@std/assert`, it **does** allow passing a generic.

Allowing us to pass a generic can also help ensure we don't make the same typo if, for example, we have to do a typescript assertion (like if we are using `.reduce` for an object with inferred keys with `Object.entries`).

E.g.
```ts
import { expect } from 'jsr:@std/expect';

interface Bar = { ... }

interface Foo {
abc: string;
def: string;
}

const barToFoo = (bar: Bar): Foo => ({ ... });

Deno.test('given bar, it returns foo', () => {
const value = barToFoo(bar);

expect(value).toStrictEqual({
acb: 'foo', // this would be allowed because the type isn't enforced
def: 'foo',
});
});
```

[`@std/expect#toStrictEqual` source](https://github.com/denoland/std/blob/main/expect/_types.ts#L790)
[`@std/assert#assertStrictEquals` source](https://github.com/denoland/std/blob/main/assert/strict_equals.ts#L32-L36)
[`@types/jest#toStrictEqual` source](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/jest/index.d.ts#L1130)

**Describe the solution you'd like**

It would be great if the type of `toStrictEqual` (and likely other matchers) could accept an optional generic so that we can get IDE completion and type checking for the values we enter, without having to make a separate variable.

E.g.:

```ts
Deno.test('given bar, it returns foo', () => {
const value = barToFoo(bar);

expect(value).toStrictEqual({
acb: 'foo', // typescript would tell us off here because `acb` isn't a property in `Foo`
def: 'foo',
});
});
```

**Describe alternatives you've considered**

(Not a _big_ deal) Creating separate variables for the values used in assertions, e.g.:
```ts
Deno.test('given bar, it returns foo', () => {
const value = barToFoo(bar);
const expected: Foo = {
acb: 'foo', // typescript would tell us off here because `acb` isn't a property in `Foo`
def: 'foo',
};

expect(value).toStrictEqual(expected);
});
```

---

I would be willing to make a PR for this if accepted :)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.