thegreenwebfoundation / co2.js

An npm module for accessing the green web API, and estimating the carbon emissions from using digital services

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Introduce just enough typescript

mrchrisadams opened this issue · comments

This issue is here to collate links or discussion about how introducing Typescript in a way that doesn't raise the bar for contribution too far so only people who are really comfortable with Typescript can contribute.

So far I've been referring to JavaScript for impatient programmers, as a guide for using javascript on the project , as it seems to be a good mix of modern js, without using too many esoteric features, and is pretty unambiguous.

The same author has another free book Tackling TypeScript: Upgrading from JavaScript, outlining how to upgrade to typescript from an existing project.

The chapter below is worth a look.

https://exploringjs.com/tackling-ts/ch_migrating-to-typescript.html

@drydenwilliams can you chime in here about a plan to follow here?

I'm moving this out of the next release.

TBH, I'm not convinced that adding Typescript adds enough to justify how much it raises the bar for making contributions.

There is a path for gradual typing to make it into the language proper listed below.

A lot of the benefits we can get from simply using jsdoc sensibly, which is good practice anyway, and we're not alone in doing this.

https://github.com/tc39/proposal-type-annotations

If you want to go the JSDoc route, I recommend reading through https://gils-blog.tayar.org/posts/jsdoc-typings-all-the-benefits-none-of-the-drawbacks/

That being said, some aspects (like tuples) cannot be expressed in JSDoc (I tried!).

Also note, that @type {import('../path/to/other/module.js).ExportedExpression} cannot be processed by JSDoc itself.
But it allows to use type definitions made elsewhere.

Thanks for this @Ryuno-Ki. I'll give it a read later this week.

Interesting discussion. I saw you've done a great job at adding JSdocs. I think the big upside with TS for a project like this is that it makes it much more likely that larger corporations will opt for using it.

Let me know if you choose to opt for TS, I would love to help in the implementation. I'm about 75% through a gradual transition of my clients codebase and it has been a fairly good experience with lots of code contributor and code-consumer value in the end.

I'm coming around more to the idea of introducing TS into this project, especially as the code base has been more complex with the recent updates in v0.12. That said, I'm not experienced with writing TS, and really only have a theoretical understanding of how it might be beneficial from a developer experience perspective for those consuming the library.

With that said, @Andersclark, could you sell me on TS from a library maintainers point of view. What benefits might we see as the custodians of this project?

I'm coming around more to the idea of introducing TS into this project, especially as the code base has been more complex with the recent updates in v0.12. That said, I'm not experienced with writing TS, and really only have a theoretical understanding of how it might be beneficial from a developer experience perspective for those consuming the library.

With that said, @Andersclark, could you sell me on TS from a library maintainers point of view. What benefits might we see as the custodians of this project?

Sorry for the late reply! I missed your post entirely. Here's my thoughts on moving a project to TS (I'm almost done moving my current project to 100% TS):

It's not as great for the developers as some people make it out to be. Types and Typescript can be frustrating and cause an initial slowdown of a project that was written for JS because writing Typescript is not just adding types to JS it changes how you write the code. Typescript also introduces additional tooling which complicates the developer environment and introduces issues (I'm currently wrestling with Webstorm's support for Vue+Typescript, which is terrible).

In my personal opinion, the drawbacks mentioned above are worth it because at the end of the day you get a more readable and reliable codebase that is much easier to contribute to and perhaps more importantly: easier to consume as a dependency. Importing a TS-based package is a great developer experience because the expectations of the package API's become very clear. This can be done with something like a @types/co2.js package as well but I don't have any experience writing separate type-packages so can't say how that would work.

I'm up for helping btw!

@Andersclark thanks for the thoughtful reply. We've opted to stick with JS Doc comments & typing for now. Though they add more lines to each file, I find them easier to read & a cleaner way to explain to everyone (not just developers) what's going on with a particular function.

I've heard that you can still have a d.ts file & import types from there into JS Doc. However I've not looked at that all that much as yet.

Hi, I would like to contribute to this task. I've created a fork of CO2.js called, aptly, CO2.ts where I'm doing the migration following the Typescript migration recipe from the Typescript Cookbook (on O'Reilly), and this blog (https://dylanvann.com/incrementally-migrating-to-typescript) which basically says use a snapshot test.

Here is the repository:

https://github.com/SekhReddy/co2.ts

If it's ever complete I will put a pull request up to try and close this issue.

I think there are pros and cons to moving to Typescript. Some are expressed here: https://www.codejourney.net/is-it-worth-migrating-to-typescript/#Bright_side_of_migrating_to_TypeScript. I think migrating to Typescript would make it easier to optimize with Rust which may help reduce the energy usage of this project in the long run. On the other hand, it raises the barrier to contribute as TS is a superset of JS. But does it really by that much?

It's also said above that JS is easier to explain to non-developers. Perhaps non-developers can be shown working tests in BDD feature file format so functionality is clear in plain english. This would also help with the issue: #98. I will attempt to work on a BDD transition to see if we can even improve (as opposed to just mitigate harm to) the ability to communicate with devs and non-devs in Typescript while also gaining all the other benefits of a migration.

I just want to make sure we're all aligned here on what this issue is about. We're looking to introduce just enough Typescript into this project. A full rewrite feels like a bit much.

That said, I understand the desire for types to be part of the codebase not just for maintainers, but also for those consuming this library. So, what would just enough Typescript look like?

An approach I'd like to follow is that of the Svelte team (they're the big name example of this, but I'm sure there are others). Their code is written in JavaScript. Type information (especially for complex types) is kept in .d.ts file. JS Doc is used for typing within the JS files, and where required it imports types from .d.ts files.

This allows us to still use Typescript, without having to go through the process of rewriting the library.

@SekhReddy thank you for the fork. Would you be up for trying the approach I've described above? We can start small - focusing on the hosting-api.js to test this out. I understand that as part of this, we'd also need to create a tsconfig.json file & have the minimum compilerOptions set to:

"compilerOptions": {
	"allowJs": true,
	"checkJs": true,
}

Hi @fershad

Looking at the code base, I don't think a full migration is "much" at all. It's actually a completely reasonable task that I would be willing to do on this separate fork. Furthermore, the process would be useful for creating the robust test suite. I think it's important that the tests reflect executable specifications than just unit tests.

I've already generated the tsconfig.json file using the tsc init function. It's in the fork if you'd like to copy it. The compiler options should actually have "checkJs" as false during a migration because otherwise you'll have JS files throwing errors for not being typescipt-compliant.

I will look at the hosting-api.js file first when I get the chance. Thanks for the quick response.

@fershad is there a feature list anywhere? Maybe user stories or some list of what the software does? It would make it easier for me to make feature files and attempt a behavior-driven migration that I can demo on hosting-api.js

@SekhReddy no, there is not. The docs are here as a reference.

Again, I want to reiterate just enought Typescript. We would welcome a Pull Request to introduce type definitions in the way I've described above. Other things beyond/tangential to that can happen at a later time.

@fershad here is a pull request for "just enough" typescript

#168

Please let me know if this is this sufficient for your intentions or if more is necessary to satisfy the "just enough" requirements. I understand that this is a larger undertaking and you have bigger priorities besides a full typescript migration. Even though I believe it is not too challenging a task, I can always come back to it in the co2ts fork at a later, more convenient time for the team.
Also, please let me know if and how I may assist on things that are higher priority than the migration.

G'day folks.

Type definitions for CO2.js are now published in the DefinitelyTyped project, and are available on NPM at @types/tgwf__co2.

You can install type definitions into your projects from NPM as devDependencies.
npm install --dev @types/tgwf__co2

Updates or changes to type definitions can be made in the DefinitelyType repo linked to above.

@mrchrisadams / @fershad wondering if you'd be open to someone looking into going just a little bit further on the typescript path. in my past experience, the main downsides to having types come from DefinitelyTyped is that those types can be out of sync from the source code. i noticed that this has come up in #196

what i would propose is:

  1. as much as possible, leave the source code exactly as-is. the files continue to be .js and jsdoc comments are used to declare types. introducing .d.ts files is a last resort for very complex types.
  2. add a "type check" step to the CI process that checks to make sure the code itself matches the types that are declared
  3. add a "type emit" step to the npm publish process that generates a full set of .d.ts files from the declared types and includes that in the published artifacts

afaik this is roughly the approach that the Svelte team has taken

full disclosure, i am a typescript fanboy, so take my opinion with a grain of salt :)

hi @sfishel18! I was just chatting with @fershad about this now, and this sounds great - it would keep the js code accessible to folks who might not know typescript, and still offer some of the key benefits from the introduction of typing in various parts of the codebase.

Your approach of the CI action, and emit step in publishing is v sensible too.

I don't know enough about how to emit the types as outlined in step 3, but if you're cool with leading on how this step would work, this sounds ideal.

So to summarise - definitely open, and you're v welcome to start, but this is a bit outside mine and Fershad's experience, so might need some handholding when getting the type emit stages set up, and adding some docs on how to troubleshoot type-check CI fails when they happen.