1
- # Closing the loop: why TypeScript and React are a superheroic dynamic duo
2
-
3
- or, the joy of tool-assisted typesafe frontend web development
4
-
5
- or, why types and the
6
- [ language service] ( https://github.com/Microsoft/vscode-html-languageservice )
7
- are superheroes of frontend web development
8
-
9
-
10
- ### *** Important update!!!* this post is * already outdated* and full of FUD and falsehoods
11
- > I unknowingly spread lies and FUD in this article comparing the capabilities
12
- > of React to Angular, Vue, Ember, and other string-based templating frameworks.
13
- > I'm sorry. Seriously. Posted to reddit and everything.
14
- > ** Nothing described here is specific to React.**
15
- > I failed to anticipate that Angular and other frameworks could theoretically parse
16
- > their string templates and integrate with a typed language like TypeScript,
17
- > and get all of the tooling benefits that React enjoys.
18
- > This very thing was [ released] ( https://blogs.msdn.microsoft.com/typescript/2017/04/27/announcing-typescript-2-3/ )
19
- > the day after I originally published.
20
- > This invalidates this article's comparison of React to Angular, Vue, and others via its new
21
- > [ language service plugin API] ( https://github.com/Microsoft/TypeScript/wiki/Using-the-Language-Service-API ) .
22
- > Here's a [ great talk] ( https://www.youtube.com/watch?v=ez3R0Gi4z5A ) .
23
- > I'm going to post a [ followup] ( https://github.com/ryanatkn/language-service-in-motion )
24
- > to this article with some snappy Angular animations,
25
- > and maybe more - [ GraphQL] ( https://github.com/Quramy/ts-graphql-plugin ) ? Yes please.
26
- > Below is a somewhat edited version of the original -
27
- > ~~ strikethrough text~~ is used to preserve mistakes and is followed by a correction.
28
-
29
- > I may just keep this repo as is, as a monument to my ignorance.
30
- > [ Here's the followup] ( https://github.com/ryanatkn/language-service-in-motion ) -
31
- > a new repo that encourages everyone to submit
32
- > animations that demonstrate the
33
- > [ language service] ( https://github.com/Microsoft/TypeScript/wiki/Architectural-Overview )
34
- > in motion for any library/framework/language/editor.
1
+ # Closing the loop
2
+ ### types + language service = awesome frontend webdev
3
+
4
+ > In the original version of this article, I mistakenly praised the capabilities
5
+ > of React compared to Angular, Vue.js, Ember, and other non-JS-based templating frameworks.
6
+ > As it turns out, tools don't care whether you put
7
+ > your code in your templates or the other way around.
8
+ > The day after I published this,
9
+ > [ TypeScript 2.3 announced] ( https://blogs.msdn.microsoft.com/typescript/2017/04/27/announcing-typescript-2-3/ )
10
+ > the stable release of the
11
+ > [ language service plugin API] ( https://github.com/Microsoft/TypeScript/wiki/Using-the-Language-Service-API ) ,
12
+ > which allows other frameworks to get similar TypeScript tooling benefits that React enjoys.
13
+ > I was wrong to say React was unique in this way,
14
+ > and almost perfectly mistimed my post, and I'm sorry if I misled you.
15
+ > Here's a [ great talk] ( https://www.youtube.com/watch?v=ez3R0Gi4z5A ) explaining
16
+ > how Angular leverages types and the language service.
17
+ > This article has been updated to clarify that React
18
+ > enjoys no special ability to take advantage of type information.
35
19
36
20
React and TypeScript are well-hyped fixtures of the 2017 webscape,
37
21
but not much attention has been given to how wonderfully they complement each other.
38
- This article and attached code demonstrate why I prefer
39
- building my views with TypeScript in React
40
- over the templating strategies used by other popular view libraries.
41
-
42
- > tldr: React builds DOM and listens to it in a way that can be typechecked.
43
- > This simple fact provides substantial benefits over alternatives that use string templates.
44
- > Read on for more discussion and visual demonstrations.
45
- > This is the joy of tool-assisted typesafe frontend web development:
46
- >
47
- > ` great web libraries/frameworks/typed languages -> great editor integration -> much productivity/happy `
22
+ This article and attached code demonstrate what's possible
23
+ in your editor when your code is fully typechecked on the frontend.
24
+ React views are written in either JavaScript or JSX, which is also just JavaScript,
25
+ so React can take advantage of types without special tooling,
26
+ but the TypeScript language service allows other frameworks
27
+ like Angular and Vue.js to enjoy similar benefits.
48
28
49
29
What follows is a whole lot of words that explain
50
30
what "the loop" is and why we want it to be "closed",
@@ -54,9 +34,9 @@ Feel free to skip down to the pretty pictures.
54
34
## What is "the loop?"
55
35
React has promoted a now well-known concept called * unidirectional data flow* ,
56
36
which has been adopted by Angular 2, Ember 2, the React community via Flux and Redux,
57
- the Vue community via Vuex, and many others.
37
+ the Vue.js community via Vuex, and many others.
58
38
This contrasts with the * bidirectional data flow* or * two-way data binding*
59
- used in Angular 1, Ember 1, Vue 1, and Knockout, among others.
39
+ used in Angular 1, Ember 1, Vue.js 1, and Knockout, among others.
60
40
61
41
There are a lot of
62
42
[ great resources] ( https://staltz.com/unidirectional-user-interface-architectures.html )
@@ -75,17 +55,20 @@ There's more to it, but this is the basic loop:
75
55
76
56
## What is a "closed" loop?
77
57
At each step of the loop, we process data sent by the previous step.
78
- In JavaScript, the correctness of passing and processing data can only be tested at runtime,
79
- and static analysis has tight limits.
58
+ In JavaScript, code that passes and processes data can only be tested at runtime,
59
+ and static analysis has tight and fuzzy limits.
80
60
In contrast, TypeScript and other typed languages are able to check more of the validity
81
61
of each step at * compile* time because of the additional information provided by types.
82
62
For the purposes of this article, I'm going to refer to a fully typechecked loop as * closed* -
83
- meaning * all* type errors will be caught by the compiler * throughout the loop* .
63
+ meaning * all* type errors will be caught by the compiler * throughout the loop* ,
64
+ for some handwavy definition of "type error".
84
65
85
66
> My apologies if the term "closed loop" irks you or makes no sense -
86
67
> please submit an issue with suggestions!
87
68
> I felt that existing terminology doesn't capture the importance of this concept
88
69
> in the context of single page web apps.
70
+ > Also a caveat: nothing here should be considered valid computer science.
71
+ > Some words with domain-specific meaning may get muddled ahead.
89
72
90
73
The benefits of having a fully typechecked * closed loop*
91
74
go far beyond disambiguating strings and numbers.
@@ -105,6 +88,8 @@ In a closed loop, the compiler has your back - all of it.
105
88
> and some things require type annotations that should be unnecessary -
106
89
> the point of this article still stands.
107
90
> Don't let perfect be the enemy of good, let alone great!
91
+ > I'm sure future tooling will make all of this appear quite barbaric,
92
+ > but it's a major improvement over webdev circa 2012.
108
93
> Be sure to check out TypeScript's optional compiler flags that increase type strictness,
109
94
> like ` noImplicitAny ` and ` strictNullChecks ` .
110
95
> The experienced TypeScript developer will likely find and prefer
@@ -117,7 +102,9 @@ Error checking is only one part of the story.
117
102
Types also provide the computer with a significantly improved understanding of your code.
118
103
This empowers the computer to do far more than check for errors -
119
104
from code navigation, to inspecting where and how which symbols get used,
120
- to making automated transformations and refactorings, there's so much the computer can do for us.
105
+ to making automated transformations and refactorings,
106
+ there's so much the computer can do for us,
107
+ which for me translates directly into productivity and happiness.
121
108
122
109
Sounds pretty good right?
123
110
The caveat is that the loop needs to be * closed* to provide a great experience.
@@ -131,6 +118,7 @@ update the variable name without the computer's assurances of validity.
131
118
This is tedious and error prone - consider renaming a property named ` text ` in a huge app!
132
119
If there can always be leaks and misses, you have to check everything manually,
133
120
and fearless refactoring flies out the window.
121
+ Worse still, your ability to understand the codebase shrinks as your app and team grow.
134
122
A closed loop enables higher productivity for reading code, writing code,
135
123
and maintaining and improving code quality over time,
136
124
which leads to happier developers, happier users, and better software.
@@ -151,49 +139,65 @@ which leads to happier developers, happier users, and better software.
151
139
So a closed loop sounds great - how do we get one?
152
140
It turns out that the * view* is where most loops get broken
153
141
in the single page web apps of 2017.
154
- This is where React differs from most other popular view libraries and frameworks.
142
+ Err, well, that was true until Microsoft introduced the
143
+ [ language service] ( https://github.com/Microsoft/TypeScript/wiki/Using-the-Language-Service-API ) ,
144
+ enabling deep integration between a typed host language,
145
+ the code inside templates, and your editor.
146
+
147
+ Authoring views is where React differs from most other popular libraries and frameworks.
155
148
If you can build your views with a typed flavor of JavaScript, like TypeScript,
156
- you can close that part of the loop! That's what React offers.
157
- Most view libraries do not allow building views with JavaScript,
158
- and even though some libraries like Vue offer this
159
- as an alternative to string templates,
160
- they still miss critical aspects of type safety, and the vast majority
161
- of the code in those communities has zero type safety in templates.
162
- Let's look at some popular frameworks and their loops with TypeScript.
149
+ you can close the parts of the loop that connect with the views
150
+ without a framework-specific language service,
151
+ and this is where React has a head-start.
152
+ Let's look at some popular frameworks that use
153
+ string-based templating and their loops.
154
+
155
+ The following diagrams ** do not necessarily imply shortcomings**
156
+ of the frameworks relative to React -
157
+ they were originally falsely diminishing in the first version of this article,
158
+ but I think they still show how helpful type information
159
+ can be in single page apps.
163
160
164
161
> ` ---> ` is a fully typechecked closed step and ` -/-> ` is a step
165
162
> that breaks the loop by losing type information
166
163
167
- Angular 2+, Vue, and Ember have ~~ two ~~ actually zero broken steps in the loop.
168
- To see what this actually means in practice, ~~ skip down to the last of the images below ~~
169
- check out the [ Vue ] ( https://github.com/octref/vetur/ ) and
170
- [ Angular] ( https://github.com/angular/vscode-ng-language-service )
171
- VSCode plugins.
172
-
164
+ Without integrating with a language service,
165
+ Angular 2+, Vue.js, and Ember have two broken steps in the loop.
166
+ Here are the VSCode plugins for
167
+ [ Angular] ( https://github.com/angular/vscode-ng-language-service ) ,
168
+ [ Vue.js ] ( https://github.com/octref/vetur/ ) ,
169
+ and [ Ember ] ( https://github.com/emberwatch/vscode-ember ) .
173
170
```
174
171
state -/-> view -/-> user input ---> business logic ---> state
175
172
```
176
173
177
- Cycle gets closer, but it prefers CSS selector strings for attaching user input handlers to the view:
174
+ Cycle.js gets closer, but it prefers CSS selector strings
175
+ for attaching user input handlers to the view.
176
+ I don't doubt that some clever tools could staticly
177
+ analyze the relationships between views and input handlers,
178
+ but they don't appear to exist today.
178
179
```
179
180
state ---> view -/-> user input ---> business logic ---> state
180
181
```
181
182
182
- React is a closed loop - no broken steps!
183
+ React is a closed loop by default, and doesn't need special tooling
184
+ to integrate with the language service - there are no broken steps!
185
+ This is a major reason why it has been adopted
186
+ by users of typed languages like PureScript and Reason/OCaml.
183
187
```
184
188
state ---> view ---> user input ---> business logic ---> state
185
189
```
186
190
187
191
Elm, PureScript, and some other languages with advanced type systems
188
192
are able to get closer to a 100% fully typechecked closed loop than TypeScript can today,
189
193
but they come with significant added friction to interoperating with the JavaScript ecosystem.
190
- This is not a tradeoff I'm willing to to make for most large applications.
194
+ This is not a tradeoff I'm willing to to make for most large applications, but YMMV .
191
195
192
196
Enough telling - seeing is believing!
193
197
194
198
## Developing with a closed loop
195
199
The following images demonstrate things that are
196
- only possible with a good type system and/ or a partially/ fully closed loop,
200
+ only possible with a partially or fully closed loop
197
201
and good editor integration.
198
202
To try these things yourself, clone this repo,
199
203
fire up your favorite editor with TypeScript integration
@@ -218,28 +222,28 @@ and start moving fast without breaking things!
218
222
### Find all references
219
223
![ Find all references] ( /img/find-all-references.gif?raw=true )
220
224
221
- ### Angular's formerly broken loop
222
- ~~ In Angular, notice how the computer
223
- doesn't help with simple typos on the component or template,
224
- despite having first-class integration with TypeScript.
225
- None of the above demos work with Angular templates.~~
226
- Stay tuned.
225
+ ### Angular's language service integration
226
+ It's not currently as complete as the React+TypeScript experience,
227
+ but Angular has partial language service integration directly in HTML files,
228
+ linking types between templates and components.
229
+ I don't see any reason why it won't be as good as React's with more time.
227
230
![ Angular 2] ( /img/angular.gif?raw=true )
228
231
229
232
230
233
## Conclusion
231
- Though imperfect, the TypeScript and React duo
232
- provide a wonderful development experience, relative to most alternatives.
234
+ Types make working with frontend code a breeze,
235
+ once you have good editor integration.
236
+ Today's tools only scratch the surface of what's possible..
237
+
238
+ Though imperfect, TypeScript provides a wonderful development experience, relative to most alternatives.
233
239
My hope is that more languages, libraries, and frameworks take seriously the idea that
234
240
we can and should be able to * close the loop* , because a fully typechecked app is a happy app.
235
- We all need heroes - not to worship, but for their leadership -
236
- and today, for front end web development, React and TypeScript are two of mine.
237
241
238
242
239
243
## Additional notes
240
- Can you do all of this with Flow, the Facebook equivalent of TypeScript?
244
+ Can you do all of this with Flow, the Facebook competitor to TypeScript?
241
245
Maybe! I don't know.
242
- The last time I evaluated Flow was over a year ago,
246
+ The last time I evaluated Flow was years ago, * (edit: see update below) *
243
247
and though it has some useful type features that TypeScript doesn't
244
248
(like [ $diff] ( https://flow.org/en/docs/types/utilities/ ) ...yet?),
245
249
the overall development experience, especially editor support and community type definitions,
@@ -250,6 +254,11 @@ to TypeScript, like `strictNullChecks`.
250
254
If you're already transpiling your JavaScript, like with Babel,
251
255
it's a modest additional cost to adopt a gradual typing technology like TypeScript or Flow.
252
256
Hopefully I've convinced you to try a typed language that compiles to JS if you haven't already!
257
+ ** update:** I used Flow for a couple weeks in mid-2017, and I found
258
+ the overall experience to be much less helpful and complete than TypeScript's.
259
+ It has a theoretically more robust type system (see "soundness")
260
+ but my experience tells me that TypeScript's leaning towards practicality,
261
+ along with its maturity and popularity, make it a far better choice for me right now.
253
262
254
263
This article is from a programmer's perspective -
255
264
designers and others may have different priorities.
@@ -266,8 +275,8 @@ can help us accomplish our goals with the right tools.
266
275
Are React and TypeScript flawless? Oh heck no! Are any big software projects?
267
276
But in my opinion, relative to other solutions,
268
277
they're good - and together, for building UIs, they're * great* .
269
- The future may hold something even better .
270
- I'm watching WebAssembly eagerly, and I think BuckleScript+Ocaml /Reason have a shot
278
+ The future will surely bring more evolution and new tools .
279
+ I'm watching WebAssembly eagerly, and I think BuckleScript+OCaml /Reason have a shot
271
280
at winning a lot of developers from TypeScript/Flow in the next year or two.
272
281
Elm and PureScript are also interesting alternatives.
273
282
0 commit comments