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

feat: add TypeScript typings #654

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

feat: add TypeScript typings #654

wants to merge 3 commits into from

Conversation

LinusU
Copy link
Member

@LinusU LinusU commented Sep 7, 2022

I've made this typings by copying in everything from the readme and then formatting it properly. Opening as a draft for now as I would like to investigate some way to make sure that the typings and readme are always in sync. Potentially ts-readme-generator or a similar script. Otherwise I fear that the typings and readme file will drift away from each other 😅

  • Write typings
  • Test readme with ts-readme-generator
    • Add support for @throws
    • Add support for @example
    • Add support for numeric literals
    • Add support for @note
    • Investigate why V1Options/V4Options isn't expanded
    • Handle overloaded functions
    • Fix @example (and others) on exported constants
  • Test typings with tsd
  • Remove runmd dependency and README_js.md file

@LinusU LinusU mentioned this pull request Sep 7, 2022
@ctavan
Copy link
Member

ctavan commented Sep 10, 2022

I think this looks really good, although – given my lack of TS experience – I can't judge the quality of the types. Questions that come to my mind:

  • Does this solve the issue raised in Have validate accept null and undefined #606 which seems to exist in the current DefinitelyTyped types?
  • In the current Types we use rather complicated interfaces. What are the pros and cons of something like that?
  • Also big +1 to auto-generating the docs from the types!

In any case, thanks a lot for putting this together and moving this long-requested feature forward!

@@ -29,7 +29,11 @@
"import": "./dist/esm-browser/index.js",
"require": "./dist/commonjs-browser/index.js"
},
"default": "./dist/esm-browser/index.js"
"default": "./dist/esm-browser/index.js",
"types": {
Copy link
Contributor

Choose a reason for hiding this comment

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

"default": "./dist/esm-browser/index.js"
"default": "./dist/esm-browser/index.js",
"types": {
"module": "./types.d.mts",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"module": "./types.d.mts",
"import": "./types.d.mts",

I've not seen module as an export condition before - could you point to its origin?

Copy link
Member

Choose a reason for hiding this comment

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

I believe this is a webpack thing, possibly adopted by other packaging tools as well?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, cool. These are types tho, and the TS docs only point to node (where the spec comes from), and they don't have a module condition listed there: https://nodejs.org/api/packages.html#conditional-exports

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 took it from DefinitelyTyped/DefinitelyTyped#57194, but it was changed to import later which is correct. Good catch! 👍

* uuidValidateV4(v1Uuid); // ⇨ false
* ```
*/
export function validate(str: string): boolean
Copy link
Member Author

Choose a reason for hiding this comment

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

In order to support #606:

Suggested change
export function validate(str: string): boolean
export function validate(str: any): str is string

Copy link
Contributor

Choose a reason for hiding this comment

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

nominal types would have made this way cleaner 😛

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah for sure!

@broofa
Copy link
Member

broofa commented Sep 13, 2022

Would it make sense to use JSDoc to document the actual source, then have tsc generate type definitions from that?

@LinusU
Copy link
Member Author

LinusU commented Sep 13, 2022

Left a note to myself to adress this 👍

  • In the current Types we use rather complicated interfaces. What are the pros and cons of something like that?

I'm actually not sure why it was made that way 🤔

It seems like it was introduced in DefinitelyTyped/DefinitelyTyped#16264.

@felipeochoa sorry for a ping for something you made 5 years ago 🙈, but do you happen to remember why use used:

export type v1String = (options?: V1Options) => string;
export type v1Buffer = <T extends OutputBuffer>(options: V1Options | null | undefined, buffer: T, offset?: number) => T;
export type v1 = v1String & v1Buffer;

instead of using an overloaded function?

export function v1(options?: V1Options | null): string
export function v1<T extends ArrayLike<number>>(options: V1Options | null | undefined, buffer: T, offset?: number): T
  • Also big +1 to auto-generating the docs from the types!

Awesome 🙌

@LinusU
Copy link
Member Author

LinusU commented Sep 13, 2022

Would it make sense to use JSDoc to document the actual source, then have tsc generate type definitions from that?

This was actually my first approach, but I ran into a number of small issues. The biggest hurdle was probably that that would generate one .d.ts file per JavaScript-file, which then would have had to been copied to all the right places since we ship so many different versions 😅 It would be cool with something similar to Rollup but for .d.ts files!

If we go that route we could also run the TypeScript compiler to type check our JavaScript codebase with --allowJs and --checkJs. It looks at the JSDoc annotations and uses that to type check the code!

types.d.ts Outdated
* uuidVersion('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ 4
* ```
*/
export function version(str: string): boolean
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
export function version(str: string): boolean
export function version(str: string): 1 | 3 | 4 | 5

or number? deffo not boolean, tho 🙂

Copy link
Member Author

Choose a reason for hiding this comment

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

Hehe, not sure how it ended up as boolean 😅

It can return 0 also, but yeah number union seems like a great return value, thanks! 👍

Copy link
Member

Choose a reason for hiding this comment

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

Hmm... worth adding a unit-test for types of some sort? Jest + tsc a few sample scripts to verify it does / doesn't throw the expected type warnings?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd recommend using tsd or something. In the jest repo we use https://github.com/jest-community/jest-runner-tsd which works great (if you already use jest), but tsd is great for type tests

@LinusU
Copy link
Member Author

LinusU commented Oct 8, 2022

I made some progress on keeping the docs in sync. The most things are already supported by ts-readme-generator, and I've added some small missing things now.

There is still some things left though, the main thing being how to handle overloaded functions 😅

But we only need a solution that's good enough for our specific needs, so that makes it a bit easier. I'm thinking now that it could compare if the overload only appends new arguments, and then merge them into just one heading. Should be quite easy!

I've put a todo list in the PR description to track what's left...

@broofa
Copy link
Member

broofa commented Oct 8, 2022

I've put a todo list in the PR description to track what's left...

Might want to add an item for removing runmd support. ( remove from devDependencies, remove README_js.md)

@LinusU
Copy link
Member Author

LinusU commented Oct 9, 2022

@broofa I haven't looked closely at exactly how to integrate it, but ts-readme-generator only modifies the ## API section of the readme, so I think that it can coexist with runmd. We could also add a flag to ts-readme-generator to just print the result to stdout, that way it could be integrated with runmd as well.

Ahh, I see now that runmd is only used in the examples in the ## API section 😅

types.d.ts Show resolved Hide resolved
@LinusU
Copy link
Member Author

LinusU commented Mar 20, 2023

Note to self: change return value to `${string}-${string}-${string}-${string}-${string}`?

ref: DefinitelyTyped/DefinitelyTyped#64798, microsoft/TypeScript-DOM-lib-generator#1432

@broofa
Copy link
Member

broofa commented Mar 20, 2023

Note to self: change return value to `${string}-${string}-${string}-${string}-${string}`?

Is this a Template Literal Type? Seems like an appropriate change.

@LinusU
Copy link
Member Author

LinusU commented Mar 21, 2023

Note to self: change return value to `${string}-${string}-${string}-${string}-${string}`?

Is this a Template Literal Type? Seems like an appropriate change.

Yes it is!

Yeah, I think it's a good change, since it would allow people to be stricter with functions that only accept uuids, and not any string 🚀


Also, sorry for falling behind on this, unfortunately I have a bit limited time at the moment, but I really want to push thru with this!

@broofa
Copy link
Member

broofa commented Mar 21, 2023

Also, sorry for falling behind on this, unfortunately I have a bit limited time at the moment

No need to apologize. We're all in the same boat. ⛵️

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.

None yet

5 participants