Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework the .toMatch() matcher #168

Open
mrazauskas opened this issue Mar 18, 2024 · 5 comments
Open

Rework the .toMatch() matcher #168

mrazauskas opened this issue Mar 18, 2024 · 5 comments
Labels
enhancement New feature or request

Comments

@mrazauskas
Copy link
Member

mrazauskas commented Mar 18, 2024

It makes sense to rethink and rework the behaviour of the .toMatch() matcher. Looking at feedback (#167) and usage it should:

  • compare only object types;
  • make sure that all target properties are present in the source (.toHaveProperty() on all properties);
  • and that their values are identical (.toBe() on all properties).

In other words, its behaviour must be similar to the .toMatchObject() matcher found in the expect library. Without any subtype checks.

The subtype checks are useful, but it would be better to implement them separately as new .toBeSubtypeOf() and .toBeSupertypeOf() matchers.

@mrazauskas
Copy link
Member Author

Transition to different behaviour would be smoother, if matcher would be renamed. I mean, it is bette to add new matcher and to deprecate .toMatch(). Looking around for a new name:

  1. .toInclude():
expect({ foo: "bar", hello: "universe" }).type.toInclude({ foo: "bar" });
expect({ foo: "bar", hello: "universe" }).type.not.toInclude({ baz: 123 });

expect<{ foo: string; bar: number }>().type.toInclude<{ foo: string }>();
expect<{ foo: string; bar: number }>().type.not.toInclude<{ baz: number }>();
  1. .toContain():
expect({ foo: "bar", hello: "universe" }).type.toContain({ foo: "bar" });
expect({ foo: "bar", hello: "universe" }).type.not.toContain({ baz: 123 });

expect<{ foo: string; bar: number }>().type.toContain<{ foo: string }>();
expect<{ foo: string; bar: number }>().type.not.toContain<{ baz: number }>();

@mrazauskas
Copy link
Member Author

mrazauskas commented Mar 20, 2024

Another idea, .toContain() could work with arrays and tuples as well:

expect<[foo: string, bar: number]>().type.toContain<[foo: string]>();

expect<[foo: string, bar: number]>().type.not.toContain<[baz: number]>();
// otherwise errors with: Type '[foo: string, bar: number]' does not contain element of type 'number'

expect<Array<string | number>>().type.toContain<Array<number>>();

expect<Array<string | number>>().type.not.toContain<Array<boolean>>();
// otherwise errors with: Type 'string | number' does not contain type 'boolean'

First TSTyche should check that objects / tuples / arrays are on both sides. If these are:

  • objects, make sure that all target keys exist in the source type and their values have identical type;
  • tuples, make sure that source contains all target elements;
  • arrays, simply make sure that target type can be assigned to source type.

@mrazauskas
Copy link
Member Author

mrazauskas commented Mar 20, 2024

Also union types could be compared:

expect<Array<string> | Array<number>>().type.toContain<Array<string>>();
expect<string | number>().type.toContain<string>();

expect<string | number>().type.not.toContain<boolean>();
// otherwise errors with: Type 'string | number' does not contain type 'boolean'

@mrazauskas
Copy link
Member Author

mrazauskas commented Mar 20, 2024

And perhaps even intersections (more complex, but interesting!):

expect<{ a: number } & { b: string } & { c: string }>().type.toContain<{ b: string } & { c: string }>();

expect<{ a: number } & { b: string } & { c: string }>().type.not.toContain<{ b: string } & { c: boolean }>();
// otherwise errors with: Type '{ a: number } & { b: string } & { c: string }' does not contain type '{ b: string } & { c: boolean }'

@mrazauskas
Copy link
Member Author

If this new matcher would work only on objects, .toMatchObject() could be a good name. Sounds familiar. Also easy to explain what it does. I'm afraid that complex behaviour as I was describing above is not a good idea.

@mrazauskas mrazauskas added the enhancement New feature or request label Mar 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant