Open studds opened 6 years ago
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, 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.
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;
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.
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?
The typings I have so far can be found here: https://github.com/Siteimprove/alfa/blob/master/packages/alfa-unexpected/types/unexpected.d.ts
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.
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
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/
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.
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
Your approach made me realise how it can be done with just a type declaration 👌 Voilá: https://github.com/Siteimprove/alfa/commit/f0fa281f3993706bbf67daedb147632594f09313
That's awesome, @kasperisager!
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?
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
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.
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.