Exploring typescript
This commit is contained in:
parent
f35db53a92
commit
0e6b18a51b
|
@ -0,0 +1,146 @@
|
||||||
|
---
|
||||||
|
layout: post
|
||||||
|
title: "Exploring TypeScript"
|
||||||
|
tags:
|
||||||
|
- javascript
|
||||||
|
- typescript
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
In my [previous post](/2018/08/30/cd-for-the-jenkins-project.html) I mentioned
|
||||||
|
[Jenkins Evergreen](https://github.com/jenkins-infra/evergreen) which requires
|
||||||
|
a significant _backend_ service to built and deployed to manage a pushed-update
|
||||||
|
lifecycle. The prototype of that service which I wrote sometime late last year
|
||||||
|
was in Ruby, but I quickly realized that my usual comfort area of Ruby and
|
||||||
|
Python were not going to meet some requirements for the service. Consequently,
|
||||||
|
I ventured into JavaScript, with the fantastic framework
|
||||||
|
[FeathersJS](https://feathersjs.com). Almost a year later, I now have some
|
||||||
|
thoughts on the strengths and weaknesses of server-side JavaScript, and have in
|
||||||
|
turn started to explore
|
||||||
|
[TypeScript](https://www.typescriptlang.org/). Overall I have found TypeScript
|
||||||
|
to be interesting, but it is not without its weaknesses.
|
||||||
|
|
||||||
|
|
||||||
|
## Complexity with External Libraries
|
||||||
|
|
||||||
|
When we first started building the Evergreen backend,
|
||||||
|
[Baptiste](https://github.com/batmat) suggested TypeScript for adding helpful
|
||||||
|
types and other features to our development of Evergreen. At the time, I was
|
||||||
|
most concerned with the added complexity TypeScript might add to a project
|
||||||
|
where nobody involved was familiar with TypeScript _nor_ JavaScript. Having
|
||||||
|
since started a couple of projects in TypeScript, I still believe this to be
|
||||||
|
the case, unfortunately.
|
||||||
|
|
||||||
|
When adding other JavaScript-based libraries to a project, they often need a
|
||||||
|
`@types` package or some other definition of what the types that package
|
||||||
|
requires for the TypeScript compiler to do proper type checking. Microsoft does
|
||||||
|
have this handy [TypeSearch web site](https://microsoft.github.io/TypeSearch/)
|
||||||
|
which makes discovering pre-existing types-packages easier. Without a
|
||||||
|
types-package however, you may need to add type declarations into your _own_
|
||||||
|
project for third-party libraries to realize benefits of TypeScript.
|
||||||
|
|
||||||
|
Assuming you understand the art and zen of TypeScript, creating these type
|
||||||
|
declaration files isn't _too_ difficult, but for the novice to intermediate
|
||||||
|
user, I believe it's still overly complex.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
For writing and executing JavaScript tests, I have been very happy with
|
||||||
|
[jest](https://facebook.github.io/jest). TypeScript and Jest _sort of_ get
|
||||||
|
along together. I recommend the additional package `ts-jest` and the following
|
||||||
|
configuration in `package.json` to ensure that TypeScript is being executed
|
||||||
|
properly within tests.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"jest": {
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.tsx?$": "ts-jest"
|
||||||
|
},
|
||||||
|
"testRegex": "(/test/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"ts",
|
||||||
|
"tsx",
|
||||||
|
"js",
|
||||||
|
"jsx",
|
||||||
|
"json",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The downside with `ts-jest` that I have found is that it's not as comprehensive
|
||||||
|
as the TypeScript compiler. This results in tests running despite compilation
|
||||||
|
failures, which leads me to question what code is actually running under test.
|
||||||
|
My workaround for this is to always maintain two terminal window panes open to
|
||||||
|
the right of my editor. One with `tsc -w`, to constantly re-compile on
|
||||||
|
filesystem changes, and `jest --watchAll` to constantly re-run tests on
|
||||||
|
filesystem changes.
|
||||||
|
|
||||||
|
By running both of these together, I get the helpful compilation errors out of
|
||||||
|
the TypeScript compiler, while still running my tests and getting the useful
|
||||||
|
test feedback.
|
||||||
|
|
||||||
|
While not ideal, when `tsc` says I have compilation errors and `jest` passes my
|
||||||
|
tests, I don't get the most confidence in those green test results.
|
||||||
|
|
||||||
|
|
||||||
|
## Outputting JavaScript
|
||||||
|
|
||||||
|
TypeScript out of the box seems to target a much newer version of ECMAScript
|
||||||
|
than Node LTS (8) or latest (10) supports out of the box. For server-side
|
||||||
|
applications, I've found the following `tsconfig.json` to result in good
|
||||||
|
Node-compatible JavaScript:
|
||||||
|
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"alwaysStrict" : true,
|
||||||
|
"outDir": "./build",
|
||||||
|
"module" : "commonjs",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"lib" : ["es2017"],
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"importHelpers" : true,
|
||||||
|
"target": "es2015",
|
||||||
|
"sourceMap": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"./src/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Of particular note are the `target` and `lib` properties which ensure that some
|
||||||
|
modern JavaScript features are made available with an appropriate output format
|
||||||
|
which will run on Node 10. Now, what features those are specifically I can no
|
||||||
|
longer remember as that was many Stack Overflow searches ago at this point.
|
||||||
|
|
||||||
|
As best as I can tell, `tsc` is rather smart in that if the configuration isn't
|
||||||
|
supposed to work with a certain version of JavaScript, than there will be
|
||||||
|
compile-time errors for some standard API calls, such as methods added to
|
||||||
|
`Array` or `String` in recent language revisions.
|
||||||
|
|
||||||
|
I'm not supremely comfortable cargo-culting configuration from one project to
|
||||||
|
another, but I have little interest at this point in time in understanding the
|
||||||
|
depths of how TypeScript is configured, and why one might choose various
|
||||||
|
options depending on the project's needs.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
In my personal projects I have yet to truly realize the benefits of
|
||||||
|
TypeScript but I have definitely been burned by the lack thereof in other
|
||||||
|
projects. Experiencing bugs which would have been prevented in TypeScript gives
|
||||||
|
me the confidence to continue the exploration of TypeScript, despite some of
|
||||||
|
the challenges it presents.
|
||||||
|
|
||||||
|
In a future blog post, I hope to outline some of the challenges faced, and
|
||||||
|
patterns needed for successfully using TypeScript together with a FeathersJS
|
||||||
|
application. Honestly though, I'm not sure I've even figured that one out yet.
|
||||||
|
And therein lies the fundamental problem with TypeScript:
|
||||||
|
|
||||||
|
It's a great add-on to the JavaScript ecosystem, but it suffers the drawbacks
|
||||||
|
of being an add-on.
|
Loading…
Reference in New Issue