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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a playground in the documentation somehow ? #132

Open
jdeniau opened this issue Feb 21, 2024 · 6 comments
Open

Add a playground in the documentation somehow ? #132

jdeniau opened this issue Feb 21, 2024 · 6 comments

Comments

@jdeniau
Copy link

jdeniau commented Feb 21, 2024

Hi,

My turn to open a suggestion 馃槃

I wanted to understand how toBeAssignable did work, but I didn't found a simple way to "play" with it :

  • I tried codesandbox, but they did change their policy about draft boxes,
  • I tried typescriptlang.org playground , but it did not throw on error,
  • I had no other idea

A possibly great feature would be to have a playground on your documentation to test type assertions live with a renderer in the browser, something similar (visually) to what storybook make on their interaction tests :

https://storybook.js.org/f2ad974cd79c81ec57476e4c3b8fb59e/addon-interaction-example-optimized.mp4

Thanks,

Feel free to close this if that's not relevant to you.

By the way, your doc is really cool for a small project, I think I will be inspired to reboot the immutablejs documentation.

@mrazauskas
Copy link
Member

Thanks. This is very nice idea. If other can make it work, this should be too hard. I will look around.

I have to add a note regarding .toBeAssignable(). It is somewhat opposite to how other marchers work and this made me struggle too. I was trying to flip the sides, but that felt wrong.

For example, we write code like this:

const x: string = 'foo';

Simply keep the same order:

expect<string>().type.toBeAssignable('foo');

@mrazauskas
Copy link
Member

Here I only speak about order as a mental model.

The type hint may change the inferred type of the expression. There is no type hint in the assertion, hence the inferred type may be different.

@jdeniau
Copy link
Author

jdeniau commented Feb 21, 2024

That's exactly why I wanted to check de documentation, it "felt" the wrong side.
It's maybe a naming problem of toBeAssignable

expect<string>().type.toAssignableWith('foo');

or something like that ? (but it's not really the issue here)

@mrazauskas
Copy link
Member

mrazauskas commented Feb 21, 2024

This is very interesting topic. I like .toBeAssignableWith() and I was considering. Naming is still an open question.

Let's look at the context first.

.toBeAssignable() is one of relation matchers. Other two: .toEqual() and .toMatch(). English is not my mother tongue, but it feels like preposition and relations fit together: .toBeAssignableWith(), .toEqualWith(), .toMatchWith(). More verbose than in expect, but also somewhat more clear.

Another aspect is the error messages. I was trying to improve readability and swapped Source and Target types:

expect<Source>().type.toBeAssignable<Target>();

// Error: Type 'Target' is not assignable to type 'Source'.
expect<Source>().type.toEqual<Target>();

// Error: Type 'Target' is not identical to type 'Source'.
expect<Source>().type.toMatch<Target>();

// Error: Type 'Target' is not a subtype of type 'Source'.

Swapping is not important for the identity matcher. But in other two cases massages are harder to understand, if Source and Target are not swapped:

// Error: Type 'Source' is not assignable from type 'Target'.

// Error: Type 'Source' is not a supertype of type 'Target'.

In expect both .toEqual() and .toMatch() do not have ending preposition. Hence I shaped .toBeAssignable() in similar way and kept swapping in error messages. Clumsy, but consistent.


It can be I was oversoaked with TypeScript's internals like "subtype" / "supertype", "assignable to" / "assignable from". Not so many people know this terminology (to be honest, I don鈥檛 feel comfortable with it too). Perhaps "with" is the solution:

expect<Source>().type.toBeAssignableWith<Target>();

// Error: Type 'Source' is not assignable with type 'Target'.
expect<Source>().type.toEqualWith<Target>();

// Error: Type 'Source' does not equal with type 'Target'.
expect<Source>().type.toMatchWith<Target>();

// Error: Type 'Source' does not match with type 'Target'.

Hm.. Looks more consistent and less clumsy. Or?

@jdeniau
Copy link
Author

jdeniau commented Feb 21, 2024

I looked at what does tsd propose, to help migration from there for those who would like to :

expectAssignable<string>('foo')

But it does feel less weird there, as the order is different

  • "expect" "assignable" type variable for tsd
  • "expect" type "assignable" variable for tstyche

So I'd rather loose the consistency with tsd.

The difference between toBeAssignable and toEqual and toMatch is that there is a Be in the first case.

English is not my spoken language either, but it does not shocks me to have a different "shape".

As a matter of fact, we can say "to love someone" and "to be in love with someone", so I'd keep the "with" with the "be" but not for the verbs.

(but take my advice with all the distance : I'm not in the type testing, nor native English!)

@mrazauskas
Copy link
Member

Thanks. Makes sense. I will keep this in mind for TSTyche 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants