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

[types] Migrate to JSDoc #528

Closed

Conversation

MysteryBlokHed
Copy link
Member

@MysteryBlokHed MysteryBlokHed commented May 26, 2024

Closes #499

This PR migrates most .d.ts type definitions to JSDoc type annotations instead. This is done in an effort to keep code documentation and implementation in the same place.

Here's a checklist with tasks that I can think of so far:

  • Files directly in src/ converted
  • Files in subfolders of src/ converted (eg. deltaE/)
  • Typing tests fixed to work with JSDoc annotations (semi-complete? runs just fine but there are type errors)

There are a few files that are currently still using .d.ts instead of JSDoc due to their complexity. Namely: color.d.ts, hooks.d.ts, index.d.ts, and space.d.ts.

Since the typings tests are currently not working, there's a chance that I've missed some bugs while doing this conversion. Once I find a way to get dtslint to run with JSDoc types, it'll be easier to spot any mistakes.

Copy link

netlify bot commented May 26, 2024

Deploy Preview for colorjs ready!

Name Link
🔨 Latest commit e3bb307
🔍 Latest deploy log https://app.netlify.com/sites/colorjs/deploys/6662291a7920df0008556369
😎 Deploy Preview https://deploy-preview-528--colorjs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@MysteryBlokHed
Copy link
Member Author

It seems like I had my editor's format-on-save using the wrong formatter, which unnecessarily messed with the code styling on a bunch of unrelated lines. I've undone some formatting changes, but I can go through and revert the other unintentional changes if desired.

@MysteryBlokHed
Copy link
Member Author

MysteryBlokHed commented May 26, 2024

One problem that I didn't think about regarding this change: for TypeScript to respect JSDoc types, you need to enable type checking for JS files. The consequences:

Screenshot of long dtslint error log

Some of these errors might just be from the files I haven't migrated yet, so I'll see how many clear up after that—hopefully to a manageable amount

@LeaVerou
Copy link
Member

Thanks for working on this!!

For no-brainer things like line break at the end of files and space when defining literals inline, I'd be fine if you just committed them directly. Then it would be much easier to review the actual changes in this PR.

@LeaVerou
Copy link
Member

One problem that I didn't think about regarding this change: for TypeScript to respect JSDoc types, you need to enable type checking for JS files. The consequences:

Screenshot of long dtslint error log

Some of these errors might just be from the files I haven't migrated yet, so I'll see how many clear up after that—hopefully to a manageable amount

Are these all? If so, that's not too bad.

@LeaVerou
Copy link
Member

It may also be worth thinking, how could we make the transition gradually?

@MysteryBlokHed
Copy link
Member Author

It may also be worth thinking, how could we make the transition gradually?

If there's any concern about how this will affect library consumers, I don't think anything will need to change—once the .d.ts files are removed, TypeScript should be able to detect the JSDoc comments and continue as usual.

Any .d.ts files that originally exported their own types have either been kept as .d.ts files alongside the JS source code, or have had their types exported like this:

/** @typedef {keyof typeof import("./index.js") extends `contrast${infer Alg}` ? Alg : string} Algorithms */

Which is equivalent to this:

export type Algorithms =
keyof typeof import("./index.js") extends `contrast${infer Alg}`
? Alg
: string;

(The @typedef directive exports the defined type by default)

@LeaVerou
Copy link
Member

If there's any concern about how this will affect library consumers,

Nah, it was more about making the work manageable for us, so that it doesn't need to be one gigantic PR by a single person.

But if you're willing to do that work, props to you!

@MysteryBlokHed
Copy link
Member Author

Nah, it was more about making the work manageable for us, so that it doesn't need to be one gigantic PR by a single person.

Ah, that makes sense. I'd be willing to finish moving the types to JSDoc on my own through this PR, but it's probably worth discussing the best way to manage the other errors that have emerged (eg. is it better to try finding a way to suppress them all, or to actually make some of the implementation code more type-safe?)

I also personally wouldn't push these changes into a release until the typings tests are working again, since there's a chance that I've accidentally introduced a TypeScript bug here that won't be caught.

@LeaVerou LeaVerou added this to the v0.6.0 milestone May 28, 2024
@LeaVerou
Copy link
Member

Nah, it was more about making the work manageable for us, so that it doesn't need to be one gigantic PR by a single person.

Ah, that makes sense. I'd be willing to finish moving the types to JSDoc on my own through this PR, but it's probably worth discussing the best way to manage the other errors that have emerged (eg. is it better to try finding a way to suppress them all, or to actually make some of the implementation code more type-safe?)

From a quick look it looks like they should all be fixable by simply making the code more type-safe?

I also personally wouldn't push these changes into a release until the typings tests are working again, since there's a chance that I've accidentally introduced a TypeScript bug here that won't be caught.

Do we know how we can do that?

@MysteryBlokHed
Copy link
Member Author

From a quick look it looks like they should all be fixable by simply making the code more type-safe?

That's true; it'd just be time-consuming. Although I am 100% willing to help if we do want to make the library's code type-safe.

Do we know how we can do that?

Right now, dtslint is just refusing to run the tests because of the type errors in the library itself. Once those are fixed, the tests will run as usual. Technically, it's doing its job exactly as it's meant to—it just means that I can't really test the JSDoc type definitions on their own until the type errors in the library are fixed.

@LeaVerou
Copy link
Member

Gotcha. I think it will be easier to fix these once this PR is merged, so there's a bit of a chicken and egg problem.

@MysteryBlokHed
Copy link
Member Author

We could just merge this once everything is re-typed with JSDoc, and then worry about fixing type errors with the library code after the fact? The only thing that's causing errors in this PR's current state is dtslint, but everything else should be fine.

I do think there are some files I still need to update (like the color spaces), but after that it should be ready.

@LeaVerou
Copy link
Member

Sounds like a plan!

Since spaces use classes, most of the typing doesn't need to be done
explicitly; JSDoc was just added to other exported functions of some
spaces.
@MysteryBlokHed
Copy link
Member Author

@LeaVerou When adding types for Format and Type, I changed the instance symbol to be an exported const instead of just a local let. That way, it can be referenced by other files in order to either index the format object, or to define types for it (like I did for the Format interface).

If that isn't wanted (i.e. the symbol should only be local), let me know and I'll undo that.

@LeaVerou
Copy link
Member

@LeaVerou When adding types for Format and Type, I changed the instance symbol to be an exported const instead of just a local let. That way, it can be referenced by other files in order to either index the format object, or to define types for it (like I did for the Format interface).

If that isn't wanted (i.e. the symbol should only be local), let me know and I'll undo that.

It was meant to be private, as how instances are associated to their spec objects is an internal implementation detail (e.g. I could have used a WeakMap) but I don't feel strongly about that at all (and tend to favor extensibility over encapsulation as a general principle)

@LeaVerou LeaVerou mentioned this pull request May 31, 2024
@MysteryBlokHed
Copy link
Member Author

It was meant to be private, as how instances are associated to their spec objects is an internal implementation detail (e.g. I could have used a WeakMap) but I don't feel strongly about that at all (and tend to favor extensibility over encapsulation as a general principle)

I could also add an @internal note to the symbol's JSDoc. It doesn't actually do anything functional, but it indicates that it's not really a public part of the API

@LeaVerou
Copy link
Member

LeaVerou commented Jun 1, 2024

Sounds good!

@MysteryBlokHed
Copy link
Member Author

At this point I think all the exported members should be documented.

To start reducing type errors, I think the next step should be to also add type information to non-exported functions. That's where many errors come from (inferred any types), and it'll also provide type hints that might resolve some errors elsewhere in the project.

@MysteryBlokHed MysteryBlokHed marked this pull request as ready for review June 2, 2024 12:49
@MysteryBlokHed
Copy link
Member Author

I can take a look at the merge conflicts later today

@jgerigmeyer
Copy link
Member

I'll try to get to this review yet this week 👍

Note: For any merge conflicts where JSDoc descriptions were removed, the
descriptions exist on the parameter's type. Basically, users will see
descriptions of each property all the same.
I have no idea how I let this through!
@LeaVerou
Copy link
Member

LeaVerou commented Jun 6, 2024

Ugh, I forgot about this and just did a mega rename. How hard would it be to rebase? I can just revert my commit if it would be tricky.

@@ -53,7 +62,6 @@ export default class Type {
/**
* Map a number to the internal representation
* @param {number} number
* @returns
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should update this, not remove it! Same for the @returns below. Happy to leave it intact as well, so that someone else can update it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I removed this because it was able to infer the return type, but we could still keep it there to document what exactly the return value represents

@LeaVerou
Copy link
Member

LeaVerou commented Jun 6, 2024

@MysteryBlokHed any chance you could move this to a color.js branch? I was trying to review but all the formatting changes are making the diff a lot bigger than it needs to be and trying to revert them with suggestions is tedious and error-prone.

@MysteryBlokHed
Copy link
Member Author

Ugh, I forgot about this and just did a mega rename. How hard would it be to rebase? I can just revert my commit if it would be tricky.

For the JS files, I think that if I just let Git auto-merge it should be able to resolve the conflicts on its own. For the typings files, it might try to recreate them all to show me the merge conflict, but I can just re-delete everything in that folder again.

I don’t think it’ll be too bad. I can try to merge it once I have access to an actual desktop (sending this reply from an iPad)

@MysteryBlokHed
Copy link
Member Author

@MysteryBlokHed any chance you could move this to a color.js branch? I was trying to review but all the formatting changes are making the diff a lot bigger than it needs to be and trying to revert them with suggestions is tedious and error-prone.

Sure thing—I should be able to in a few hours.

@MysteryBlokHed
Copy link
Member Author

If I'm not mistaken then you should also have write access to this branch on my fork (just through the way GitHub PRs work), but I can move it to color.js anyway if that makes it easier

I think all imports should still be correct after this?
@MysteryBlokHed MysteryBlokHed mentioned this pull request Jun 6, 2024
3 tasks
@MysteryBlokHed
Copy link
Member Author

Closing in favour of #540 (same thing, but the source branch isn't on my fork)

@LeaVerou
Copy link
Member

LeaVerou commented Jun 7, 2024

If I'm not mistaken then you should also have write access to this branch on my fork (just through the way GitHub PRs work), but I can move it to color.js anyway if that makes it easier

Oh, good point. Oh well, too late now. Anyhow, in the future I think it's better to use branches in the repo itself.

@MysteryBlokHed MysteryBlokHed deleted the types/migrate-to-jsdoc branch June 7, 2024 15:56
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

Successfully merging this pull request may close these issues.

How to have a single source of truth for types and docs?
3 participants