Feathers: Proposal: Switch to TypeScript for Development

Created on 1 May 2017  ·  31Comments  ·  Source: feathersjs/feathers

__IMPORTANT__: Feathers 4 and later comes with built-in TypeScript support. Please see the docs for more information

Propose switching to TypeScript

In another thread, @marshallswain asked what the benefits are, and nobody really answered.

TypeScript has already reached the StackOverflow volume of CoffeeScript and is getting close to the number of GitHub repos. I know that is subjective, but if you think about the relatively small amount of time TypeScript has been around it is pretty impressive. Someone asked above about the value TypeScript would provide the core team. Here are the benefits as I see them, even for JavaScript Unicorns.

  1. It is just sugar on top of JavaScript, so while it is a few extra keystrokes, you really won't notice much difference
  2. All of your existing ES2015+ knowledge moves over with you, you can use as much or little of the extra features as you want.
  3. You get a great amount of type safety for those extra keystrokes. Meaning it will tell you immediately if you are passing the wrong number or kind of parameters to a function. It might slow you down at the very beginning, but after a few days your velocity will actually be higher than before you used it, because you find a lot of mistakes before you even try to compile.
  4. If you write the code for this project in TypeScript, you get completely accurate declarations for the community for free. It's just a compiler switch at that point and where you want to output them. This will increase your user base greatly and will probably add some contributors as well. This brings Angular support with no extra effort. If you don't know already, Google mothballed AtScript and decided to write Angular 2+ in TypeScript.
  5. You can add TypeScript gradually, since TypeScript is just a super-set of JavaScript, every JavaScript file is TypeScript already, and the compiler will happily compile it along with TypeScript in most cases.
  6. This isn't just code completion, the compiler is statically analyzing your project for Type Errors the entire time. Every experience I have read about that has converted JS projects says it detected bugs they didn't even know they had.
  7. With projects like TypeDoc, you get very easy API documentation with types included, but not required.
  8. Consumers can still choose to use regular ES5 and should not even care that you wrote it in TypeScript.
  9. You can get features like unions, where you can say type switcher = "on" | "off" | "disabled", then you can say in your function changeLightStatus(newState: switcher), now if I try to pass "enabled" it will immediately complain that "enabled" is not a valid option and that I must specify "on", "off" or disabled. That is pretty awesome.
  10. You will make a lot of people happier than you already have with this amazing project, that I really want to use, but won't until there is proper TS support.

To be clear, this isn't meant to be a "which is better" type of discussion. There is nothing wrong with the code you have, it is both beautiful and elegant. I am trying to make the case, that you will get a lot of added value for very little effort.

I know this is bordering on a dead horse, I would just ask that you please do some research to see if it is a good fit for you and your team. There is a large group of us passing on this, because once you start using it, going back to being without it seems archaic. Again, there is nothing wrong with what you are doing now, that archaic feeling is only something you experience after using it for awhile. I am describing the feeling, not your code base or any other.

I would definitely appreciate your careful consideration and I know myself and others in the community would be willing to help.

Discussion Proposal

Most helpful comment

Typing will eventually come to JavaScript, just like the best of CoffeeScript goodness did.

I doubt the JavaScript typing will be exactly the same as TypeScript for multiple reasons including politics, including Flow, including shortcomings in TS. The good ideas will be taken, the bad won't be.

Projects using TS will then face the same problem that ones using CoffeeScript did. They have code that's too similar to the new standards but not fully compatible with it.

Externalized definitions are a nice compromise.

  • People will not bypass Feathers because its written in TS. (Let's not forget npm packages written in CoffeeScript mostly were ignored even though they were transpiled to JS.)
  • We don't have to remove the TS when standards do arrive.

All 31 comments

Not as easy as you might think. Feathers relies on ES5 inheritance and mixins, so it's doubtful that switching to TS would "just work".

How to work with Feathers in TS, from j2L4e: https://github.com/feathersjs/feathers/issues/381#issuecomment-298607510

As an aside "others in the community would be willing to help" is not true. We've asked the people vocal about TS to help with no reply, only more requests. One person stepped forward but again the people vocal about TS didn't step up to help finalize the definitions. We finally moved the TS definitions out of the project because of that lack of support.

If you want to help, we would appreciate it if you updated the definitions and placed them in DefinitelyTyped.

__TL;DR__ We need __someone__ to submit finalized definitions of current Feathers core (which are mostly done anyway) to the DefinitelyTyped repository. I will work with that person to eliminate any blockers caused by odd things Feathers might do. If this works, I will bring up using TypeScript for the next version of Feathers core with the team. If not I don't think there is enough general interest or that the TypeScript community is reliable enough to warrant taking such a major step.

I have been thinking more about what it means to create and maintain a code base that is used and contributed to by many people and will hopefully last a long time and I agree that TypeScript might be a sensible choice. We are using a transpiler already so using TS instead of Babel wouldn't be that much of a change and personally I'd be ok with some throwback to my Java days for getting an additional layer of security and stability. We will definitely not have the core codebase fragmented across multiple languages however so it is a decision the entire team has to make (non-core plugins can be maintained either way).

I don't really have anything against the language but as @eddyystop pointed out, our experience with the TypeScript community has been rather disappointing so far. There were many vocal members requesting support and pointing out all those great benefits - some of which always seemed kind of strange to me like claiming that TS is fully compatible with JavaScript but in almost the same paragraph pointing out that people won't use your JavaScript project until it supports TS. When it came to _actually doing something_ however, only less than a handful of people (whose contributions and effort we do appreciate) tried to move things forward but the ball keeps getting dropped for one reason or another and we never got much actionable feedback on what we can do to keep things rolling.

If it is like @j2L4e pointed out just some weird usage of mixins for services, then that is something that we are trying to fix in the next version anyway by defining a core service interface like

interface Service {
  find(params: any),
  get(id: string|number, params: any),
  create(data: any, params: any),
  update(id: string|number|null, data: any, params: any),
  patch(id: string|number|null, data: any, params: any),
  remove(id: string|number|null, params: any),
  setup(app: FeathersApp, path: string)
}

And an extended interface of the wrapped service which will be returned by app.service:

interface FeathersService extends Service, EventEmitter {
  hooks(hooks: HooksObject),
  filter(filters: FilterObject)
}

Some additional things to clarify about TS for me would be:

  1. I don't want the usage of Feathers if you don't use TS to change whatsoever. Since I think type checking is happening during transpilation this should already be the case but I don't want anybody to get weird TS specific errors if you are not using it.
  2. What is transpiled code size? Currently all of client side Feathers is ~20k minified + gzipped. I am not a library size maniac but I wouldn't want this to change significantly just because the pre-transpiler language is different. Also, what browsers is it compatible with and what additional runtime does it require?
  3. If we are using typed interfaces already I'd like to be able to generate API documentation markdown from typings + inline docs. Are there any serious tools for doing this?

I'm a little short on time right now, so a couple of words only:

I don't want the usage of Feathers if you don't use TS to change whatsoever.

RxJS is native TS and it works really well with JS. Getting away from the mixin-style may impose breaking changes, but there's nothing specific to Typescript that would.

What is transpiled code size?

TypeScript can compile to ES3, ES5 or ES6. I fact it was common for some time to compile to ES6 and use Babel to compile it down to ES5 when TS's ES5 support wasn't that great. I think ES3 compilation imposes some limitatoins, I've never used it myself and why would you?
When you compile to ES6 it basically strips out the type annotations and there's your JS code. Async/await, import and decorators aside there's nothing that would need compilation when you target ES6. TypeScript's compiled ES5 code is also known to be very readable:

(code samples from 2 years ago, all i could come up with in 30 sec)
ES6 class: https://gist.github.com/fariszacina/515e4c81704d839ea490#file-simple-es6-example-js
compiled with TS (target ES5): https://gist.github.com/fariszacina/6287b4213ebf6965d05e#file-simple-es6-example-typescript-output-js
compiled with Babel: https://gist.github.com/fariszacina/dc8d5c7c17c5b2ab01ee#file-simple-es6-example-babel-output-js

In terms of code size: I doubt that it's any bigger than what Babel can offer. I can try it out on the weekend.

Also, what browsers is it compatible with and what additional runtime does it require?

Any that run ES5 and no runtime. What comes out of the TS compiler is plain JS.

generate API documentation markdown from typings + inline docs.

https://github.com/TypeStrong/typedoc

You can also generate JSDocs from TS definitions and go ahead from there.

Typing will eventually come to JavaScript, just like the best of CoffeeScript goodness did.

I doubt the JavaScript typing will be exactly the same as TypeScript for multiple reasons including politics, including Flow, including shortcomings in TS. The good ideas will be taken, the bad won't be.

Projects using TS will then face the same problem that ones using CoffeeScript did. They have code that's too similar to the new standards but not fully compatible with it.

Externalized definitions are a nice compromise.

  • People will not bypass Feathers because its written in TS. (Let's not forget npm packages written in CoffeeScript mostly were ignored even though they were transpiled to JS.)
  • We don't have to remove the TS when standards do arrive.

FWIW, I agree with @eddyystop -- Javascript is evolving faster than any other language out there. Thanks in great part to Babel and other such tools that accelerate the development of the language.

I will contribute however I can, assuming everyone is onboard.

You have built something amazing and I believe this will make it accessible to a lot more people.

@j2L4e Mixins are supported. I am not sure what you mean by inheritance, but if you mean subclasses, they have been supported since day 1 AFAIK. If you can do it in ES2015, you should be able to do it in TypeScript, since it is a superset.

@daffl To answer your questions:

  1. I don't see any reason the API would have to change. No TS compiler errors will leak out to JS users. Trasnspiled size has actually been slightly smaller than Babel in my experience, however unless you disable type-checking build time goes up slightly. Like 20 seconds becomes 22 seconds.

  2. It will drop you dependency count greatly, because all that is required is a loader and the TypeScript compiler. Browser compatibility is entirely dependent on what you tell TypeScript to target. It will target browser compliant ES3, 5, or 2015, 2017 if you want it to. It's just a compiler switch instead of presets in the form of npm packages like Babel.

  3. typedoc works really well for this. Here is an example

Here is the playground where you can try it out including an inheritance example. It gives you a view into what will be output without having to invest the time in downloading tooling.

Not saying it cant be done in TypeScript. Just that the way it works now (uberproto) is hard to get typed. Especially stuff like feathers-reactive that replaces the service methods.

I had put together some stuff regarding the Coffeescript vs. TypeScript comparison but closed the browser by accident :/ i'll try again tonight.

Am 4. Mai 2017 18:49:28 MESZ schrieb Mike Morrison notifications@github.com:

I will contribute however I can, assuming everyone is onboard.

You have built something amazing and I believe this will make it
accessible to a lot more people.

@j2L4e
Mixins are
supported. I am not sure what you mean by inheritance, but if you mean
subclasses, they have been supported since day 1 AFAIK. If you can do
it in ES2015, you should be able to do it in TypeScript, since it is a
superset.

  1. I don't see any reason the API would have to change. No TS compiler
    errors will leak out to JS users. Trasnspiled size has actually been
    slightly smaller than Babel in my experience, however unless you
    disable type-checking build time goes up slightly. Like 20 seconds
    becomes 22 seconds.

  2. It will drop you dependency count greatly, because all that is
    required is a loader and the TypeScript compiler. Browser
    compatibility is entirely dependent on what you tell TypeScript to
    target. It will target browser compliant ES3, 5, or 2015, 2017 if you
    want it to. It's just a compiler switch instead of presets in the form
    of npm packages like Babel.

  3. typedoc works really well for this. Here is
    an example

Here is the
playground
where you
can try it out including an inheritance example. It gives you a view
into what will be output without having to invest the time in
downloading tooling.

--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
https://github.com/feathersjs/feathers/issues/565#issuecomment-299243699

--
Diese Nachricht wurde von meinem Android-Gerät mit K-9 Mail gesendet.

You all need to focus on how to do what you want to do using external TS definitions.

@eddyystop Pretty divisive comment from the person complaining about the TS community. Keep in mind this is my first interaction with the Feathers community. Should I assume the rest of the team is going be the same?

I don't think it was meant to feel divisive, @mizzle-mo. Sorry if it came across that way. His reply is based on previous conversations. We opted to keep the TypeScript definitions stored separately, since it hasn't been championed by somebody who understands it. It's impossible for any of the core team to fix it, but the issues continue to roll in and get backed up. Keeping it in a separate repo seemed like the logical choice. Is there a downside to keeping the definitions separate?

We will have some pretty solid TypeScript definitions for the next release thanks to the great work @j2L4e is doing but Feathers core will continue to use only the latest language features all versions of Node Feathers is intended to run on natively support.

@daffl may I ask "when"? I'm starting a new project with feathers and it'll be great if am able to use TS

There's not much left to be done and there are two holidays coming up in Germany, so I'll be able to get most of it done (i.e. typings) vefore next week.

@j2L4e awesome, thanks

join #typescript on the feathers slack to get updates on this

I would love to help with this too. I've been doing some work on the typings for several projects (Feathers, feathers-plus/cli, feathers-vuex, as well as some Nuxt modules).

I cant view messages on the slack past Nov 2018. But I would be interested in getting this rolling, but I think we need a decent idea of what the migration would look like before starting.

Converting the code itself to TS is a much more political decision than TS proponents might realize.

What would be the other factors to take into consideration? I can't speak for other projects of course but for @feathersjs core, if the external API surface doesn't change it would mainly affect regular contributors to the codebase.

In the past year and a bit this has been @bertho-zero, myself and the outside TS definition maintainers (spearheaded by @j2L4e). Personally I've been using TS for internal projects for a bit now and can see how it could benefit a project like Feathers core (e.g. when it comes to implicit documentation, backwards compatibility and client side builds) so I wouldn't be opposed to this move as long as there are other people helping out. Sure it might deter non-TS users from contributing (or maybe not looking at the activity of Jest which is using the much more obscure Flow Types) but as it stands right now, the way things are doesn't seem to be particularly encouraging for repeat contributions either.

@daffl honestly, I think my learning of feathers and how the internals work could be greatly improved by typescript. Even if it is just the Ctrl+click to jump to the declaration. Some things I've tried to dig into jump around a bit. I am also spoiled by Typescript at this point though, so maybe that's why. And again I'm very familiar with Typescript, but I also have the opinion that newcomers to Typescript think it's intimidating to think about, but surprisingly easy to contribute to.

I know you have to take this type of thing with a grain of salt, but right now I am really excited about feathers and would love to contribute more. I've been pretty busy with the Holidays and catching up on work recently. But I'd like to start contributing more in the coming weeks.

I've started converting feathers to TS, and have so far completed feathers, commons, and configuration. The progress is available at https://github.com/thavlik/feathers

The main issue I have ran into is with exporting default functions. I propose all default exports be changed to sensibly named exports.

@daffl
(a) I have concerns that the ECMAScript ecosystem is forking into JS and TS, which I feel is not to the ecosystem's advantage.

This may sound to you and others like a trifle but I worked with Microsoft near the executive level in the mid 1990's and this was the sort of situation they tried hard to engineer. The people I knew then would be overjoyed with the situation today with TS. (Full disclosure: I worked with the anti-IBM efforts.)

I'm not saying the people at MS today are similar to the ones there then (nor am I saying they are not), but I feel this new-age version of MS's embrace-extend-destroy strategy is as dangerous now as then. It leads to MS calling the shots on the ecosystem and you can bet they will move in a direction beneficial to themselves.

(b) I would consider using TS if I again ran dozens of software developers which usually means a lot of juniors. However my Feathers work is solo and I can't remember the last time I had a bug involving types. So using TS would be unnecessary overhead.

(c) Running a preprocessor on the server just slows me down. I'm also slowed down running tests. The feathers-hooks-common npm test used to take seconds, now it checks the typing with a fair number of TS versions and I in fact go get a coffee or chat someone up whenever I run the full test.

(d) You and I do over 95% of the dev of Feathers. I have a month's long backlog. I would think you are in the same situation. Authentication needs a rewrite as it causes a majority of the Feathers issues. There's the rewrite of hooks to use generators. Do you still want to use uberproto?

I don't think rewritting into TS is a priority.

(e) I would think having typings for the Feathers API gives TS users what they need. Rewritting into TS is overkill.

(f) I still look forward to the day ECMAScript introduces typings and I'm likely to start using them then.

@thavlik
That's a JS issue as well. Nicholas Zakas is someone who has done very smart stuff in addition to ESLint. https://humanwhocodes.com/blog/2019/01/stop-using-default-exports-javascript-module/

I completely agree with what @eddyystop says about this:

(e) I would think having typings for the Feathers API gives TS users what they need. Rewriting into TS is overkill.

As I mentioned to @eddyystop and @marshallswain before, I'm not happy with how much of this project is dependent on myself and I'd be more than happy to try new things to get more people involved and make it easier to contribute. Since we already have all the definitions, I don't believe that converting the codebase would be an insurmountable task (keep in mind that all of @feathersjs is only 2k lines of code) and the usage wouldn't change so the worst case scenario I'm seeing is that I still do all the work but people get better code completion in their editors. It would also line up well with some of the other changes that are planned.

I am currently using TS in several internal projects and although I don't consider it the end-all-be-all, there are several things (outside of the usual TS-fan laundry-list) that I think would be beneficial to Feathers core:

__Pros:__

  • Use of modern ES features in a well-defined and stable environment without having to rely on experimental Babel plugins
  • A unified language environment that isn't dependent on the runtime you are using (no more async/await breaking Node 6 or some ES feature not working in IE)
  • ES module builds (something coming up all the time and not likely to be a part of Node any time soon) that allow client-side bundle size optimization using tree shaking
  • Code completion and inline API docs (now supported by most editors)
  • No more TS definition issues

__Cons:__

  • Might deter people that don't know TS from contributing
  • Compile step might slow down tests and introduce some additional maintenance effort
  • It's work that somebody has to do
  • Bikeshedding over TypeScript stuff (if any of my feature proposals would have a fraction of the discussion that TypeScript issues had I'd feel a little more like people actually care about Feathers as a project and not just what their favourite programming language is).

@daffl quick comment to your last pro and last con. Like I said I'm just getting into feathers, but some issues with definitions threw me off. Which is why it's the first area that I'm commenting on. I think a mitigating factor is the flexibility of typescript to just throw an as any, but I strive to have the "no any" complier option on. So as to @eddyystop and @marshallswain comments about the typings actually is harder without generating typings from typescript code. (Mostly in advanced topics such as oauth verifier and handler and such). Also I find definitely tpyed is a hassle to contribute to.

Again. I'd love to pitch in on the work, mostly because I'm more comfortable contributing to typescript code bases. By no means take that as feathers needs to change though. I'm happy to contribute with plain ol' JavaScript too.

I happily volunteer to do the work, but the default exports are liable to change some. An example of this work is available in my fork, where I basically integrated the declaration files already written and added some argument types where I saw it was clearly appropriate.

The tests can compile into js and run just as quickly. And as long as the default export semantic is not used, the scripts require almost no additional type annotation to compile without warnings.

@NickBolles @thavlik Can we sync up in the #typescript channel on Slack? Will put a summary here but it's probably easier to figure out what the plan is there (and if/how things could be broken up).

I was actually considering this framework now that we are re-constructive our massive intranet, but WHAT you don’t even have type definitions, you don’t wanna go typescript since you rely on es5 mixins? What kind of dinkie toy, mickey mouse joke project is this, a world moving towards all typescript just take angular and the top frameworks good luck generating torque with your rated nr 98 ”es5 mixing relying framework” that was the only thing that really put you ahead, we even considered this over sails.js

@duffman wow. Seems like an off the cuff response there.

There are typescript types, see https://github.com/feathersjs-ecosystem/feathers-typescript (after a simple search on the feathers documentation). If there are any issues with the types let me know/make an issue on that repo and I'd be happy to take a look.

Please note that feathers being written in typescript has little to do with users using the library (with typescript or not), except for the higher possibility of typings issues. I would highly recommend using feathers and feathers-plus cli+ as it generates typescript scaffolding for you, I have had very few issues, and those issues could easily be solved by declaring my own interface, or casting to any. A small price to pay for the benefits of typscript IMO

If you have something constructive to add to the conversation (like offering to help convert feathers to typescript) by all means contribute, but that comment seems pretty innacurate and harsh. If you have questions maybe the slack channels are a better place.

I'm going to close this since I don't think this issue will lead to any further constructive discussion and already solicited several uninformed comments and unnecessary arguments. TypeScript is supported in Feathers v4 or later.

Was this page helpful?
0 / 5 - 0 ratings