Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Which TypeScript codebase should I study to get better?
158 points by nblavoie on Nov 9, 2017 | hide | past | favorite | 73 comments
I've been doing TypeScript professionally for the last 8 months or so and I would like to push further my knowledge of the language by reading well documented and high profile app or packages. Any suggestions ?



The TypeScript compiler is the canonical corpus of code written by TypeScript experts, and I learned a lot of interesting style from the time I've spent with it. (Fun fact: they don't use 'class' in the compiler at all, but instead have a different pattern for passing around interfaces+state that is much more TypeScript-y.)


Could you cite an example of the interfaces+state pattern? You've piqued my interest.


Seconded, I'm also very interested.


It looks like there is a lot of legacy code hanging out in the compiler [1], i.e. prefer module over namespaces.

[1] - https://github.com/Microsoft/TypeScript/blob/master/src/comp...

It's also strange to me why they inline their interfaces, rather than organizing them in a common folder / module.


Fun fact: they don't use 'class' in the compiler at all

Looks like a class to me: https://github.com/Microsoft/TypeScript/blob/master/src/comp...


What strikes me first is the comment above the function :

// Keep the class inside a function so it doesn't get compiled if it's not used.

I didn't know it was possible.


We do use classes in the test harness, services layer, and to polyfill es6 Map. We just don't use them in the design of any compiler subsystems.


This is very interesting to me.

Is the reasoning behind this documented anywhere?

I could only find instructions the coding guideline indicating as much (here: https://github.com/Microsoft/TypeScript/wiki/Coding-guidelin...) but couldn't find why. I'd love to know why, may better inform my usage of typescript.


For better or worse? I've avoided classes in our codebase because I don't like the lack of privates via closure (revealing module pattern) and it's transpiler overhead, but it's a very powerful organization tool. I've found code to be much neater in the class format.


Looks like C++ circa 2008. Careful with those abstractions. That seems a stone's throw away from template metaprogramming.


does anyone have some recommendation on how to debug typescript compiler, it seems like console does not work there, I am trying to just step through tsc.ts, but gulp local always complains that console is not defined. Is there any alternative in stepping through the compiler?



I second this. Not only is the code well-written, the whole codebase is architected in a modular and layered way. Many things are well documented. You can probably step up your game and write a plugin for VSCode as an exercise.

The VSCode codebase is evidence TypeScript is built to scale further then Javascript.


Its editor component "Monaco" is the single reason that TypeScript exists. TypeScript was created in conjunction with (or for) this first project, of course the editor was first used in other parts of MS, and only later was also integrated into VSC.


How does one approach looking at a (large) codebase with intent to learn? Where do you begin?


Read "Working Effectively with Legacy Code"


    if (!!process.send
Is there something I'm missing here? Why not just:

    if (process.send


`!!x` is guaranteed to evaluate to a boolean value of `true` or `false`.

`if (x)` evaluates truthiness of `x` which in Javascript land might behave differently. I don't know how off the top of my head, but I know it's something to be cautious of in this language and its derivatives.


An if statement works exactly the same whether you pass it a boolean true or false, or any truthy or falsy expression.

In other words, these are 100% equivalent:

  if( anything ) { ... }

  if( !!( anything ) ) { ... }
The !! is redundant here, unless there's something relevant that isn't shown in the if statement excerpt in legohead's comment.


It's just explicit coercion.

If there was a linter rule I could turn on to require booleans in if-conditions, I'd enable it.

`!!` might seem silly, but it's a hint that you intended for coercion to happen. A similar but better example would be preferring `if (x > 0)` over `if (x)` even though non-zero is truthy.

There's an even better case for returning `!!x` from a function even though you could return `x` and let the call-site coerce it. The problem with that is that the call-site can build a dependency on the value of `x` beyond truthy vs falsey.

In a weakly typed language like Javascript, I don't think you'll ever regret being a little more explicit.


> `!!` might seem silly, but it's a hint that you intended for coercion to happen.

"Silly" is in the eye of the beholder, of course. But it is definitely redundant. Using a value in an if statement is not just a hint, but an explicit guarantee that all you are doing with the value is testing it for truthiness. !! adds no information or insight that isn't already there.

> A similar but better example would be preferring `if (x > 0)` over `if (x)` even though non-zero is truthy.

Obviously you know this, but if( x > 0 ) is not the same thing as if( x ). You can't substitute one for the other: a truthiness test on x is different from testing the numeric value of x for being greater than zero. If x is -1, the two statements will do different things.

> There's an even better case for returning `!!x` from a function even though you could return `x` and let the call-site coerce it. The problem with that is that the call-site can build a dependency on the value of `x` beyond truthy vs falsey.

That's a completely different situation. When you return a value from a function, there is no guaranteed truthiness test as there is with an if statement. You're just returning a value "as is".

So for example, if you have a function that creates some private object and it's defined to return a truthy or falsy value to tell you if the object was created, it could be tempting to say "I have a variable with a reference to the object I'm creating or null if it failed. I can just return that variable!"

As you mentioned, the caller could hold a reference to that return value, thus holding a reference to the object that isn't necessary - and could lead to a memory leak. By using "return !! myObject;" instead, you avoid passing the object itself back to the caller and just give them a true/false value instead. This is a good thing to do.

But an if statement is not the same thing. The if statement already has a guarantee that all it will do with the value is test it for truthiness and not keep any reference to it. Adding !! doesn't convey any information to the reader that isn't already there.

I like being explicit too, but I don't like adding extra verbiage to something that is already completely explicit.


TSLint has this: https://palantir.github.io/tslint/rules/strict-boolean-expre...

It doesn't play well with the vscode tslint extension for some reason (doesn't show up at all) so you need to run tslint manually to see the errors.. but it's better than nothing.


But that also includes operands to !, so you wouldn't be able to use !! to bool-ify something.


> In a weakly typed language like Javascript, I don't think you'll ever regret being a little more explicit.

"!!" is not needed in the shown case. It might be needed if you want to pass somewhere or return "boolean" value, but in the example it's only the "if" thing.


I much prefer the more explicit `Boolean(anything)` for this reason.


I think you're right. It looks like an oversight.


Opening the VS Code inside VS code? I would feel watched, like my VS Code is wondering what the hell I'm doing.

Is it not good enough for me? Is it failing me in some awful way that I feel compelled to change it? Maybe it should get out of the IDE business if its not good enough? Maybe become a farmer, take a break from technology


Or you can think about it as looking under the hood of a car, or taking apart an iPhone to appreciate the beauty. But I do love the irony. I imagine people have run binary decompilers on the decompilers themselves before.


I remember the tale someone fuzzing the same fuzzer to find bugs. I can't find the link though.

General tools like an editor, a decompiler, or even an image editor can be used to modify the software itself. After all, if you're the creator of the tool itself, most likely you feel comfortable using it.

What I always wonder is how people built the first tools. How did people compile the first version of GCC? How did people build the first programming language? How did people built the first OS? I can imagine ways to solve these, but I guess the tale behind how they did it is what makes me wonder.


The general term is "Bootstrapping" https://en.wikipedia.org/wiki/Bootstrapping_(compilers)

Generally you start with "something smaller/easier" and build your way up.


I learnt a lot from looking at the code code base when it was first released (and back when TS didn't have so much material available).


If you want to learn more about 3d engines (game or rendering), I would recommend BabylonJS: https://github.com/BabylonJS/Babylon.js

It has fairly good docs: http://doc.babylonjs.com/ as well as an active forum for developers and users: http://www.html5gamedevs.com/forum/16-babylonjs/

Other options mentioned are also good - the Typescript compiler (https://github.com/Microsoft/TypeScript) is good to get started with especially if you read this Gitbook: https://basarat.gitbooks.io/typescript/content/docs/compiler...

You could also search popular typescript github projects that are more closely related to what you work on, but the Typescript compiler and Babylonjs 3d engine are both well written projects with fairly good documentation in my opinion.


Three i've read through recently:

1. InversifyJS - DI in Typescript / JS

https://github.com/inversify/InversifyJS

2. TypeORM - as it says, might be the best ORM for nodejs projects:

https://github.com/typeorm/typeorm

3. Searchkit - ES web frontend - react + typescript

https://github.com/searchkit/searchkit


+1 for InversifyJS - I learned a lot of TypeScript by just reading through the actual Inversify codebase, and then used what I learned to write what would become https://github.com/inversify/inversify-express-utils.

Also, thanks to the Inversify contributors for continuing to maintain and improve express-utils!


+1 for InversifyJS from me too. I've also been looking at the inversify express utils lately -- loving it so far!

Do you know if there are any plans for allowing the http context (req, namely) to be injected into services? Similar to the IHttpContextAccessor in dotnet core?

I have some use cases for using pieces of the http context (headers) to instantiate some transient services. I started putting together my own pieces to see what I could get away with. Looks like it works okay, but I had to create a new container per request, using the `Container.parent` to link them.


This should be possible now. You can implement by yourself as described at https://twitter.com/RemoHJansen/status/927542673682116611. I have already started to think about a way to add this into the inversify-express-utils but I have to think it well so it can support all kinds of auth.


HttpContext is now available in inversify-express-utils@4.2.2 https://github.com/inversify/inversify-express-utils#httpcon... :)


funny i'd just bookmarked inversify-express-utils the other day and have been meaning to go back to it :)

the Typescript ecosystem has really come a long way


The TypeScript compiler itself is written in TypeScript: https://github.com/Microsoft/TypeScript


That's cool but surely any implementation of a language in itself is going to deal with some pretty fringe situations, so it might not be the best thing to read in order to learn how you should write other things in that language?


There's no reason why implementing a language in itself would be special, it's not dealing with fringe situations in any sense of the word. It is traditional to write compilers in the very language they compile, except for slow interpreted languages, and a compiler is a very well-studied type of program that includes a variety of different types of code such as straight text processing, error reporting, and recursive data structures. Compilers are often used as test beds for new language features, famously, Niklaus Wirth would measure language improvements based on how much they would improve the language's compiler.

Think about it this way: a TypeScript compiler takes a bunch of text as input, and produces a bunch of text as output. That's not really special or weird, is it?

(The only hard part is the “bootstrapping problem” which is what happens when you want to write a compiler for language X using language X, but you can’t compile it because you don’t have a compiler yet.)


a TypeScript compiler takes a bunch of text as input, and produces a bunch of text as output. That's not really special or weird, is it?

In the case of a compiler used for production, it may have lots of optimizations, most of the time, this optimizations are non-idiomatic code that's hard to understand and its purpose its not obvious.


Can you give an example of this? Most of the compilers I've seen have excellent code bases, with good separation between the different components, probably because compilers are so well-studied. It can be surprising what the most productive part of the compiler is to optimize. Often the lexer is heavily optimized due to its outsized impact on performance, but even then, the code looks idiomatic to me.

- Scanner.Scan() https://github.com/golang/go/blob/master/src/go/scanner/scan...

- scan() https://github.com/Microsoft/TypeScript/blob/master/src/comp...

- Lexer::LexTokenInternal() https://github.com/llvm-mirror/clang/blob/master/lib/Lex/Lex...

All three examples are heavily optimized and hand-written but they’re still clear and easy to follow.


Interested in that bootstrapping process. Is it just that the first version has to be compiled with some other language. From then on, you just use the previous version that you have compiled already?


Yes, that is normal. If you can imagine, this process dates back to the first assemblers, which were written in assembly and then converted by hand to machine code.


From what I recall, start by writing a minimal compiler for language X in some other language, Y, and compile it. Now you have an X-compiler written in Y.

Rewrite the minimal compiler in X, and compile it using the one that was written in Y. That gives you an X-compiler written in X compiled from one written in Y.

To be sure _that one_ works, recompile your X source code with that last compiler. Now you have a compiler written in X and built with one also written in X.

Continue to add more features written in minimal-X to get X-compilers with more X features.


Just as small improvement, for the first step an interpreter is a better approach, just to ease the bootstraping process by not having to write a compiler backend twice.


Exactly what I was thinking while browsing the code. In particular, I'm looking for the "right way" to code the application. Using Observable, Promise, patterns, etc. To get to the point that I don't ask myself all the time if it's the right way to do the things.


A caution: I’ve observed a lot of code that’s been damaged by enthusiastic use of patterns or library features, and I’ve met novice programmers who doubt whether their code is good code based solely on the fact that it doesn’t use Observable, Promise, patterns, etc.

Look for code that is correct, clear, concise, testable, etc.


I really love this ORM project for typescript:

http://typeorm.io/

It's also one of the larger enterprise grade projects that i've seen done natively in TS. It pretty much uses all the bells and whistles that the language provides. Some decent patterns, and an active developer community.


A little off topic, but is anyone using this in a large production environment? I'm currently using sequelize for a side project and haven't been terribly happy with it. TypeORM looks better but it feels like it has just sprung out of nowhere and is maybe too new to use in the real world.


Project I know just replaced sequelize with TypeORM and is about to go into production - the beta has been great

There is this issue talking about production readiness with more feedback:

https://github.com/typeorm/typeorm/issues/591

You should know about quirks like this one:

http://typeorm.io/#/relations-faq/avoid-relation-property-in...

I've been spending more and more time reading the code and tracking the open issues - getting comfortable with phasing it into a production system


We use TypeScript heavily at Ionic.

Ionic Framework 2+ is TS: https://github.com/ionic-team/ionic

Our new web component compiler Stencil is also TS: https://github.com/ionic-team/stencil


Nice. Simple question. How do you educate your developers on TypeScript or Angular? What is the training path they follow to become top notch?


No specific education, just jump in and follow existing patterns. Most devs we hire pick it up quickly and we have people here that can help with more complicated questions. We have a few people who really grok the type system and can help with nasty type issues when they come up.


GitHub Desktop is 92% TypeScript: https://github.com/desktop/desktop


And what about the "TypeScript Design Patterns" book, you guys have read it ? Is it good ? Is it worth the investment ? http://amzn.to/2ym40AW And what about Online Courses on Udemy?


I recently wrote and submitted a pull-request to DefinitelyTyped. Find non-Typescript packages and add the typings :).


Or, if you're a hero, find the packages with bad typings and fix them <3333


My favorite is finding the libraries that now have typings (they migrated to TS themselves or got a good definition PR they accepted, maybe even a PR you sent the library directly), and sending the removal PR to DT. DT is huge so every file that can be removed is a little bit less of a papercut in checkout time and testing time for the next branch/developer.


and please break the codebase of people using these types by not following semver (keeps happening to me with typings -_- should really start using a lock file)


This is a great discussion! Reading good code is the best way to learn.

Reading the NativeScript code gave me a really good impression of TypeScript, although I'm just learning it and haven't written much yet myself.

https://www.nativescript.org/using-typescript-with-nativescr...

I have a huge blob of old JavaScript cellular automata code I want to rewrite in TypeScript, but first I want to read some good TypeScript code before starting so I don't mess it up.

It has a bunch of old "frameworky" meta-programming code and data structures that I've painted myself into a corner with (see the "type definitions" comments), which I'd like to throw away and re-implement from scratch, because TypeScript is much better suited for that kind of stuff. And then there's a bunch of brute force bit bashing and number crunching code that I hope will just run without any modification and only a little repackaging, which is another nice benefit of TypeScript.

https://github.com/SimHacker/CAM6/blob/master/javascript/CAM...


If you're going to be doing React - the Blueprint source (Palantir's react ui kit) seems to be really well written. I don't work there... I just use it.

https://github.com/palantir/blueprint/tree/master/packages/c...


Few questions:

1. How has been your experience with Blueprint JS?

2. Is it possible to take a look at your work?

3. Would you recommend using it? If yes, what types of apps?


I use it for internal admin type apps. Can't really show to it you though sorry.

It is pretty damn thorough tho and the css is relatively minimal if you need to custom skin the components.

Yes I would recommend it highly. Just look through the components they have mostly everything covered.


The firebase web SDK is written in TypeScript: https://github.com/firebase/firebase-js-sdk


Rxjs is another good one.

https://github.com/ReactiveX/rxjs


I would take an existing vanilla JS project if you have one, and convert it. I learned a lot there. You can also learn a lot of the conventions by using/studying TSLint. https://github.com/palantir/tslint




lit-html is relatively short and well documented.

https://github.com/PolymerLabs/lit-html


Depends. How good are you at JS? Because I think learning what great JS looks like will give you a better grounding in what TS is actually adding to JS and what is “good TS” vs “good general practice”.

That might sound dismissive of TS but it’s not, I’m just trying to get a sense on what you’re trying to learn from TS.


Not to toot my own horn but I quite like my personal project, an HTTP client for the Toxiproxy server (a programmable TCP proxy).

https://github.com/ihsw/toxiproxy-node-client




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: