govuk-frontend icon indicating copy to clipboard operation
govuk-frontend copied to clipboard

Export type declarations for component source code

Open jhackett1 opened this issue 3 years ago • 6 comments
trafficstars

it would be great if this library declared its types, to make it easier to understand what i can import from it and how it can be used.

at the moment, when i import it in a typescript project, i get an error:

Could not find a declaration file for module 'govuk-frontend'. '/Users/jayehackett/Downloads/wp-fiddle/node_modules/govuk-frontend/govuk/all.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/govuk-frontend` if it exists or add a new declaration (.d.ts) file containing `declare module 'govuk-frontend';`

i could perhaps make a pull request for this if it's wanted?

Context

Alternatives

i could define some a declaration file in my own project, but that would only solve the problem for me!

Additional information (if applicable)

for a library like this, including types is a useful form of self-documentation. it's nice to be able to import a library and see intellisense suggestions for what i can do with it without having to refer to a documentation website.

for example, this works, but my editor doesn't "know" that it works:

Screenshot 2022-09-11 at 18 26 45

jhackett1 avatar Sep 11 '22 17:09 jhackett1

here's an example @cloudratha did for the hackney fork of this lib. doing it here would probably look similar:

https://github.com/LBHackney-IT/lbh-frontend/pull/177

jhackett1 avatar Sep 11 '22 17:09 jhackett1

Thanks @jhackett1 for raising this issue

I know things have been quiet (or silent) from our end on this but it's certainly been talked about.

For now, you're likely seeing problems because "strict": true is set in your TypeScript compilerOptions. For any regular JavaScript code without type declarations, ours included, you'll see the same.

Microsoft have some more tips here for regular JavaScript: https://code.visualstudio.com/docs/languages/jsconfig

Tip: jsconfig.json is a descendant of tsconfig.json, which is a configuration file for TypeScript. jsconfig.json is tsconfig.json with "allowJs" attribute set to true.

Generated type declarations in future

That said, we appreciate type declarations are a brilliant way of bringing documentation straight to the code

What could we do in the future?

  1. Manually write type declarations
  2. Keeping our JavaScript source, but output type declarations via tsc + JSDoc
  3. Converting to TypeScript source, but compiling to JavaScript with type declarations via tsc

Mainly with 2) in mind, we've started taking a look at improving our JSDoc comments as we know the TypeScript compiler (and your editor or IDE's language server) will automatically pick these up

Automatic type discovery now

What do we have already?

If you're using an editor or IDE (Visual Studio Code, Sublime Text, WebStorm) with plugins that wrap the TypeScript standalone server (aka tsserver) you'll already see type information from node_modules appearing in your code.

I had a quick try and our JSDoc comments (where we use them) are appearing already 😊

JSDoc comment for Checkboxes prototype syncAllConditionalReveals shows available params

For anyone else searching I'll put these notes here

Thanks again

colinrotherham avatar Oct 12 '22 16:10 colinrotherham

To add to this, our workflows over at the Planning Inspectorate would benefit from exported types. For now we are defining our own types to go along with the library.

We use plain JavaScript instead of TypeScript, but TS is key to understanding the types a library needs, and is what vscode uses to check code too.

We often have a need to know the type of a nunjucks macro function - i.e. what data can we pass to a particular macro; being able to check the types for that (and have it autocomplete etc...) would be useful.

beejjacobs avatar Sep 04 '23 07:09 beejjacobs

We're going to put this one back in the backlog for a bit, the time to prioritise our work.

romaricpascal avatar Jan 16 '24 14:01 romaricpascal

Just a note from TypeScript’s Publishing guide as they suggest types are published by either:

I’ve picked the easiest option 1) to generate types alongside source (#4094, #4154) so this caveat applies:

If your types are generated by your source code, publish the types with your source code. Both TypeScript and JavaScript projects can generate types via declaration.

Which would then steer us away from DefinitelyTyped:

Otherwise, we recommend submitting the types to DefinitelyTyped, which will publish them to the @types organization on npm.

But to avoid accidentally-breaking type changes, perhaps this still leaves an optional @govuk-frontend/types package as a valid option, without DefinitelyTyped?

Type checking Nunjucks

In future, we could consider a custom filter or function (opt-in only) that enables Nunjucks type checking:

We often have a need to know the type of a nunjucks macro function - i.e. what data can we pass to a particular macro; being able to check the types for that (and have it autocomplete etc...) would be useful.

The filter could log warnings or throw errors at Nunjucks compile time when options are deprecated or invalid:

govukAccordion({
  rememberExpanded: false
} | validate('AccordionConfig'))

Autocomplete

Unfortunately, code autocomplete via types would only be available in JavaScript templating languages.

We'd need to move our YAML documentation into JSDoc to support this and I've demonstrated JavaScript versions of govukAccordion(), govukBackLink() etc in https://github.com/alphagov/govuk-frontend/commit/a4c0877707f589ddb540ea62bfcd226287ce2d1d on branch component-data-jsdoc

https://github.com/alphagov/govuk-frontend/blob/39c0a23edd3c47c27954c601168d1ede342c3920/shared/lib/components.js#L154-L156

JavaScript versions of govukAccordion(), govukBackLink() etc are wrappers for our render('accordion', options) Nunjucks lib functions used by our tests, but ensuring that options either becomes a JSDoc @template matched on the component name or separate JSDoc block

If support was needed, these wrappers could be used in JSX and other JavaScript templating languages

colinrotherham avatar Jan 18 '24 11:01 colinrotherham