Converting your vanilla Javascript app to TypeScript

The Javascript language has gone via many updates all through its lengthy (in web phrases) historical past. Together with its
quickly altering ecosystem and maturing developer base got here makes an attempt to ease a few of Javascript’s shortcomings. Of be aware,
one of many extra important makes an attempt was CoffeeScript (preliminary launch in 2009) which provides
syntactic sugar and options that make programming simpler.

In late 2012, TypeScript was publicly launched at model
0.8 1 . Just like CoffeeScript, TypeScript tried to
add extra options onto Javascript. The largest function TypeScript dropped at the desk, as its identify implies, was varieties.
Sorts, and all different options that construct on prime of varieties reminiscent of generics, have been already loved by builders on different
languages like Java and C#, however this felt like the beginning of one thing massive for Javascript.

Quick-forward to 2016 – the primary time TypeScript is talked about
on Stack Overflow’s Developer Survey. In 2016, a whopping 0.47% of
survey respondents have used TypeScript. Skipping forward two extra years
to the 2018 survey and TypeScript jumps to 17.4% of
respondents utilizing TypeScript. You in all probability get the place that is heading now. In
the most recent survey (2021) TypeScript jumped to 30.19%, even transferring
previous languages like C# and PHP. That is positively an indication that TypeScript is one thing to concentrate to and possibly
your vanilla Javascript app may use somewhat makeover.

This submit will undergo an instance TODO app repo we’ve arrange
right here: https://github.com/anvilco/anvil-ts-upgrade-example. This repo is in plain vanilla Javascript and runs on Node.js
and makes use of Specific. There are some primary exams included, nevertheless it’s so simple as might be. We’ll undergo a couple of methods
that one can take when making an attempt emigrate to utilizing TypeScript from Javascript.

This submit won’t undergo TypeScript programming ideas in depth and can solely gloss over them briefly since these
are big chunks of data themselves. The
official TypeScript Handbook is a good useful resource in order for you
to be taught extra.



Step 0

Earlier than beginning, it’s vital to know our start line with our app’s performance. We’d like exams. In case you don’t
have any, it’s value it to a minimum of create a couple of exams for completely happy path exams: that’s, exams that do the only “good”
factor.

Additionally value mentioning earlier than you begin: have your code on a versioning system (i.e. git). A number of information are prone to
change and also you’ll need a straightforward solution to undo all the pieces.



Set up TypeScript

Easy sufficient. Let’s get began:

$ npm set up --save-dev typescript
# or 
$ yarn add --dev typescript
Enter fullscreen mode

Exit fullscreen mode

TypeScript is a superset of Javascript, so any legitimate Javascript program can also be a sound TypeScript
program 2 . Primarily, if we run our code via the TypeScript
compiler tsc (which is offered whenever you set up typescript above) with none main issues, we needs to be good to
go!



tsconfig.json

After putting in, we additionally must arrange a primary tsconfig.json file for the way we wish tsc to behave with our app. We
will use one of many really useful tsconfig information
right here: https://github.com/tsconfig/bases#centralized-recommendations-for-tsconfig-bases. This incorporates a listing of
group really useful configs relying in your app sort. We’re utilizing Node 16 and wish to be extraordinarily strict on the
first move to scrub up any dangerous code habits and implement some consistency. We’ll use the one
situated: https://github.com/tsconfig/bases/blob/main/bases/node16-strictest.combined.json.

{
  "show": "Node 16 + Strictest",
  "compilerOptions": {
    "lib": [
      "es2021"
    ],
    "module": "commonjs",
    "goal": "es2021",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "allowUnusedLabels": false,
    "allowUnreachableCode": false,
    "exactOptionalPropertyTypes": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noPropertyAccessFromIndexSignature": true,
    "noUncheckedIndexedAccess": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "importsNotUsedAsValues": "error",
    "checkJs": true,
    // Every little thing beneath are customized modifications for this app
    "allowJs": true,
    "outDir": "dist"
  },
  "embrace": [
    "./src/**/*",
    "./__tests__/**/*"
  ]
}
Enter fullscreen mode

Exit fullscreen mode



Compile and repair errors

Now let’s run tsc:

$ yarn tsc
# or 
$ npx tsc
Discovered 68 errors in 5 information.

Errors  Recordsdata
    13  __tests__/app.check.js:1
    28  __tests__/retailer.check.js:3
    14  src/app.js:1
     1  src/fashions/Todo.js:4
    12  src/retailer.js:13
error Command failed with exit code 2.
Enter fullscreen mode

Exit fullscreen mode

68 errors. Not too dangerous particularly with extraordinarily strict guidelines on. Lots of the errors are “implicitly has an ‘any’ sort”
and will have straightforward fixes.

Apart from these, there are a couple of fascinating errors:

src/app.js:1:25 - error TS7016: Couldn't discover a declaration file for module 'specific'. 'anvil-ts-upgrade-example/node_modules/specific/index.js' implicitly has an 'any' sort.
  Strive `npm i --save-dev @varieties/specific` if it exists or add a brand new declaration (.d.ts) file containing `declare module 'specific';`

1 const specific = require('specific')
                          ~~~~~~~~~

src/app.js:2:28 - error TS7016: Couldn't discover a declaration file for module 'body-parser'. 'anvil-ts-upgrade-example/node_modules/body-parser/index.js' implicitly has an 'any' sort.
  Strive `npm i --save-dev @varieties/body-parser` if it exists or add a brand new declaration (.d.ts) file containing `declare module 'body-parser';`

2 const bodyParser = require('body-parser')
                             ~~~~~~~~~~~~~
Enter fullscreen mode

Exit fullscreen mode

These error messages inform us learn how to repair the errors and likewise level to how components of the typing system works in TypeScript.
Packages can present typing declarations (with the *.d.ts file extension). These are generated robotically via
the tsc compiler. When you have a publicly accessible TypeScript app, you can too present official typing declarations
by submitting a pull request to the DefinitelyTyped repo: https://github.com/DefinitelyTyped/DefinitelyTyped.

The 2 packages within the snippet are extremely popular modules, in order that they’ll positively have sort declarations:

# We’re additionally including in sort declarations for modules utilized in testing: supertest, jest
npm i --save-dev @varieties/body-parser @varieties/specific @varieties/supertest @varieties/jest
# or
$ yarn add -D @varieties/body-parser @varieties/specific @varieties/supertest @varieties/jest
Enter fullscreen mode

Exit fullscreen mode

Let’s verify on tsc:

Discovered 15 errors in 3 information.

Errors  Recordsdata
     2  src/app.js:13
     1  src/fashions/Todo.js:4
    12  src/retailer.js:13
error Command failed with exit code 2.
Enter fullscreen mode

Exit fullscreen mode

From 68 errors to fifteen. That’s rather more manageable. The remainder of the errors ought to now be truly associated to our personal
code. Let’s take the one which repeats probably the most:

src/retailer.js:28:16 - error TS7053: Component implicitly has an 'any' sort as a result of expression of sort 'any' can't be used to index sort '{}'.

28     let merchandise = localStore?.[id]
                  ~~~~~~~~~~~~~~~~
Enter fullscreen mode

Exit fullscreen mode

What does this imply? Our localStore variable is an Object, however its key sort is any. In strict TypeScript, we have to
be clear what our indexes might be. On this case we use numbers as indexes.

Earlier than we repair this, let’s change our file’s extension to the *.ts: retailer.js -> retailer.ts. It will let tsc know
it is a TypeScript file, in addition to our IDE. Now we begin truly writing TypeScript.

interface LocalAppStore {
  [key: number]: typeof TodoModel
}

const localStore: LocalAppStore = {}
Enter fullscreen mode

Exit fullscreen mode

We’ve created our first interface. It tells the TypeScript compiler what a LocalAppStore object seems to be like with its
keys as numbers and its values as a TodoModel.

We additionally must create a brand new interface TodoData which defines the article we move to create and replace Todo
cases.

// src/fashions/Todo.ts  (renamed from Todo.js)
export interface TodoData {
  id?: quantity,
  title?: string,
  description?: string,
}
Enter fullscreen mode

Exit fullscreen mode

We are able to then import that interface and use it as sort annotations all through the app.

With out getting too verbose and explaining all the opposite smaller errors, you possibly can check out the department we’ve right here
to see what modified: https://github.com/anvilco/anvil-ts-upgrade-example/tree/ts-convert.

In abstract, after putting in TypeScript and creating its config file we:
Get tsc to run with out failing – not together with errors it finds in our code Search for any lacking sort declarations. In
this case we have been lacking varieties from jest, specific, body-parser, and supertest. Rename information from .js to .ts
Repair errors by creating sort aliases or interfaces, including sort annotations, and so forth. This will doubtlessly take probably the most time
as you’ll want to check out how features are used, how and what sort of information is handed.

One factor to remember is that the migration course of to TypeScript might be performed at your personal tempo. Since legitimate
Javascript can also be legitimate TypeScript, you don’t need to rename all information to .ts. You don’t need to create sort
interfaces for all objects till you’re prepared. Utilizing a less-strict tsconfig.json
file (https://github.com/tsconfig/bases/blob/main/bases/node16.json), along with // @ts-ignore feedback to disregard
errors you don’t agree with or possibly aren’t prepared for but.



After compiling

After tsc lastly compiles your undertaking, chances are you’ll want to regulate your bundle.json file. In our bundle.json we
have:

  "essential": "src/server.js",
Enter fullscreen mode

Exit fullscreen mode

which now factors to a file that doesn’t exist. Since this could level to a Javascript file, we have to replace this to
level to the compiled model:

  "essential": "dist/server.js",
Enter fullscreen mode

Exit fullscreen mode

Notice that you will want to compile your app code each time your entry level must be up to date. This may be performed
robotically as you develop with packages reminiscent of tsc-watch
and nodemon.

It’s also possible to see if the compiled model of the app runs manually via a command like node dist/server.js.



IDE Assist

One of many main unwanted effects from migrating to TypeScript, in the event you use a supported IDE reminiscent of Visible Studio Code or one
of the JetBrains IDEs, is healthier integration with the IDE. This consists of, however isn’t restricted to, higher autocomplete and
higher popup hints for operate varieties (see picture beneath). This brings the language a lot nearer to typed, compiled
languages like C# and Java.

(./ide-support.png)



Different tooling

This submit has solely lined a really slim migration case involving a primary Node.js app and some unit exams. Actual
functions are rather more advanced than this and would contain different transpilers and builders reminiscent of webpack, rollup,
and babel. Including TypeScript to these construct processes can be separate weblog posts themselves, however I imagine the final
recommendation right here continues to be 100% relevant in advanced conditions.



Conclusion

Migrating an app to a different platform or language is rarely straightforward. Fortuitously, if you wish to migrate your vanilla
Javascript app to TypeScript, it may be performed progressively, as quick or as sluggish as you need. Moreover, the TypeScript
compiler might be configured to offer as a lot suggestions as we’d like all through the method to make sure your code runs.
Hopefully this submit has impressed you to a minimum of take into consideration the opportunity of migrating your Javascript app.

At Anvil, we’ve begun migrating a few of our public initiatives to TypeScript as nicely. Up to now it’s been painless and pretty
easy. In case you’re growing one thing cool with our libraries or paperwork automation, tell us at
builders@useanvil.com. We would love to listen to from you.

Add a Comment

Your email address will not be published. Required fields are marked *