unexpected icon indicating copy to clipboard operation
unexpected copied to clipboard

Typescript typings

Open studds opened this issue 7 years ago • 16 comments

Would you be open to a PR with some basic typescript typings, so that this can be used in typescript projects? They might not cover the full breadth and depth of the API, but would cover the most frequent use cases.

studds avatar Oct 02 '18 06:10 studds

I'm currently working on TypeScript typings for Unexpected with a goal to cover as much of the API as possible. Since I need the typings for plugin development I expect to use the majority of the APIs available.

On a related note, might @papandreou or @sunesimonsen have an opinion on where these typings should live? They're currently internal to the project I'm working on but I'd love to make them more easily available. I know some people swear to DefinitelyTyped, which is a great resource for typings and all, though I do personally prefer as a consumer of a library not to have to install additional packages for things to Just Work™.

kasperisager avatar Nov 08 '18 09:11 kasperisager

@kasperisager, that sounds really cool! If we can find a way to automatically generate the typings from the assertions that are defined and their types, I would be open to have the typings live in Unexpected itself. I remember @bruderstein talked about that idea earlier and seemed quite confident that it could be done.

If they have to be manually maintained, I think it would be better to keep them separate for the time being, as none of the maintainers use TypeScript, AFAIK.

papandreou avatar Nov 08 '18 11:11 papandreou

That can absolutely be done, though the core typings (expect(), use(), clone(), addAssertion(), etc.) would still have to be maintained somewhere rather than generated. Currently, expect() is only minimally typed:

function expect<A extends Array<unknown> = []>(subject: unknown, assertionName: string, ...args: A): expect.Unexpected;

What could be done then is generate overloads based on assertion signatures, e.g. something like this...

expect.addAssertion<Person, [number]>(
  "<Person> [not] to be older than <number>", 
  (expect, subject, age) {
    // ...
  }
);

...would generate the following overload for expect():

function expect(subject: Person, assertionName: "to be older than" | "not to be older than", age: number): expect.Unexpected;

kasperisager avatar Nov 08 '18 11:11 kasperisager

I agree with @papandreou if it is not almost hands off then if should probably live somewhere else. The very dynamic nature of unexpected means that it will never be fully covered. But you might create something useful anyway. I don't use TypeScript, so I'm personally not super interested in maintaining it. But I can imagine an external project that takes the newest version of unexpected installs the most common plugins inspects the types and handlers on the unexpected instance and generates the type definitions.

sunesimonsen avatar Nov 08 '18 16:11 sunesimonsen

fwiw, the official recommendation from the typescript team in this case would be to publish the types to the @types organisation on npm, which is done by submitting a PR to https://github.com/DefinitelyTyped/DefinitelyTyped.

The types could still be generated, of course. Has anyone made a start on this? @kasperisager are your types currently available anywhere publicly?

studds avatar Nov 12 '18 00:11 studds

The typings I have so far can be found here: https://github.com/Siteimprove/alfa/blob/master/packages/alfa-unexpected/types/unexpected.d.ts

kasperisager avatar Nov 16 '18 10:11 kasperisager

This is really interesting - as it happens I recently did an experiment for the other part of this, which is to actually get auto-completion when writing assertions in test call. I'll see if I can get them cleaned up and arrive at a definition for all the assertions in core.

alexjeffburke avatar Dec 02 '18 23:12 alexjeffburke

I've fleshed out the types we're using internally in preparation for opening a PR on DefinitelyTyped. I've also tried to combine with what you've got, @kasperisager. We're not doing any plugin development, though, so I'm not sure if this will work for that - would you mind having a look and letting me know?

https://github.com/studds/DefinitelyTyped/blob/master/types/unexpected/index.d.ts

studds avatar Dec 11 '18 04:12 studds

I've pulled in your typings to see if our packages still type, and it looks like the only thing missing is either a general overload for the expect() function (similar to https://github.com/unexpectedjs/unexpected/issues/525#issuecomment-436966420) or the addition of optional conditions such as "[not] to be" which are used when defining new assertions: http://unexpected.js.org/api/addAssertion/

kasperisager avatar Dec 11 '18 08:12 kasperisager

The general overload would actually be required regardless as there would otherwise be no way to invoke custom assertions. One of the issues I ran in to when implementing the typings used in our project was also that I couldn't find a way to allow plugins to define additional overloads for the expect() function, effectively making custom assertions only minimally typed. Unexpected itself will catch issues arising from that at runtime though so it was an acceptable trade-off.

kasperisager avatar Dec 11 '18 08:12 kasperisager

Ahhh, yes, that is a problem. I can't figure out how to get around that with plain types.

Can I propose a different approach, in that case: wrapping unexpected and re-exporting it in a way that makes it more typescript friendly: https://github.com/studds/unexpected-ts#readme publish as https://www.npmjs.com/package/unexpected-ts

studds avatar Dec 12 '18 04:12 studds

Your approach made me realise how it can be done with just a type declaration 👌 Voilá: https://github.com/Siteimprove/alfa/commit/f0fa281f3993706bbf67daedb147632594f09313

kasperisager avatar Dec 12 '18 07:12 kasperisager

That's awesome, @kasperisager!

studds avatar Jan 25 '19 00:01 studds

I ended up going @kasperisager 's typings and works for me (with a few tweaks).

IMHO, I don't think typing up all the different assertions is a terribly good idea. We add quite a few assertions of our own, and AFAIK, we wouldn't be able to add those to TSC run-time, making strict checking a no-go. The only benefit left is editor-typeahead (which I don't use much).

How about we get a MVP typings thing shipped and take it from there with adding more fancy stuff?

msiebuhr avatar Aug 01 '19 12:08 msiebuhr

IMHO, I don't think typing up all the different assertions is a terribly good idea. We add quite a few assertions of our own, and AFAIK, we wouldn't be able to add those to TSC run-time, making strict checking a no-go. The only benefit left is editor-typeahead (which I don't use much).

On the contrary, the typings I've written allow both for strongly typed core assertions in addition to weakly typed custom assertions that can then be made strongly typed by extending the Expect interface from outside as seen here: https://github.com/Siteimprove/alfa/blob/f0fa281f3993706bbf67daedb147632594f09313/packages/alfa-unexpected/src/create-unexpected-plugin.ts#L10-L17

kasperisager avatar Aug 01 '19 13:08 kasperisager

Presumably one could take advantage of the (relatively) new template literal types to generate many possible assertions with only a few lines of declarations.

I'd love to be able to use this library, but without IDE support/completion of the assertion strings, it's a lot less appealing.

shicks avatar Nov 28 '21 05:11 shicks