TypeScript

give it a try

and you'll save time

Sorry for terrible rhyme :(

Excuses

a.k.a. strong opinions

My excuses were:

  • It's probably hard to configure with existing app
  • I have no time to rewrite my app to .ts
  • I don't need types, I managed well with dynamic typing for years
  • It's probably another overhyped tool for hipster developers. What's next, Elm language?

It's probably hard to get started

Rails & Webpacker

bundle exec rails webpacker:install:typescript

When starting new React App

Custom setup

  • install typescript and ts-loader using yarn/npm
  • configure your webpack config and tsconfig.json
  • install typescript-eslint (optional)
2
// tsconfig.json

{
    "compilerOptions": {
        "module": "system",
        "noImplicitAny": true,
        "removeComments": true,
        "outFile": "./lib/bundle.js",
        "sourceMap": true
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules",
        "**/*.spec.ts"
    ]
}
// webpack.config.js

module.exports = {
  mode: "development",
  devtool: "inline-source-map",
  entry: "./app.ts",
  output: {
    filename: "bundle.js"
  },
  resolve: {
    // Add `.ts` and `.tsx` as a resolvable extension.
    extensions: [".ts", ".tsx", ".js"]
  },
  module: {
    rules: [
      // all files with a `.ts` or `.tsx` 
      // extension will be handled by `ts-loader`
      { test: /\.tsx?$/, loader: "ts-loader" }
    ]
  }
};

I have no time to rewrite my app to .ts

Current (JS) state

Magic words: `any` and `void`

function distance(source, destination) {
  return Math.sqrt(
    Math.pow(source.x - destination.x, 2) +
    Math.pow(source.y - destination.y, 2)
  )
}

// is actually seen by typescript as:

function distance(source: any, destination: any): any {
  return Math.sqrt(
    Math.pow(source.x - destination.x, 2) +
    Math.pow(source.y - destination.y, 2)
  )
}

Let's introduce real types

function distance(source: any, destination: any): any {
  return Math.sqrt(
    Math.pow(source.x - destination.x, 2) +
    Math.pow(source.y - destination.y, 2)
  )
}

// with types:

function distance(
  source: { x: number, y: number },
  destination: { x: number, y: number }
): number {
  return Math.sqrt(
    Math.pow(source.x - destination.x, 2) +
    Math.pow(source.y - destination.y, 2)
  )
}

And DRY it a little...

function distance(
  source: { x: number, y: number },
  destination: { x: number, y: number }
): number {
  return Math.sqrt(
    Math.pow(source.x - destination.x, 2) +
    Math.pow(source.y - destination.y, 2)
  )
}

// DRY it:

interface Vector { x: number, y: number }

function distance(source: Vector, destination: Vector): number {
  return Math.sqrt(
    Math.pow(source.x - destination.x, 2) +
    Math.pow(source.y - destination.y, 2)
  )
}

Fully TS, yay!

interface Vector { x: number, y: number }

function distance(source: Vector, destination: Vector) : number {
  return Math.sqrt(
    Math.pow(source.x - destination.x, 2) +
    Math.pow(source.y - destination.y, 2)
  )
}

See, that wasn't so bad, was it?​

How it looks with OOP:

class User {
  name: string
  age?: number
  role = 'guest'

  constructor(name: string, age?: number, role?: string) {
    this.name = name
    this.age = age
    if (role) this.role = role
  }

  isAdmin() {
    return this.role === 'admin'
  }
}

And with React Component:

import React, { FunctionComponent } from 'react';

type Props = {
  title: string,
  paragraph: string
}

// we can use children even though we haven't defined them in our CardProps
const Card: FunctionComponent<Props> = (props) => (
  <div>
    <h2>{ props.title }</h2>
    <p>
      { props.paragraph }
    </p>
    { props.children }
  </div>
)

What is it good for?

🍰 Sweet IDE integration 🍰

Expose dangerous code 🐛

It's here and it will remain for ​a long time

According to NPM:

Text

According to Slack:

According to Tom Dale, EmberJS creator:

Alternatives

... and in case previous arguments didn't work

USE TYPESCRIPT

Thanks

Sources

TypeScript

By Maciek Walusiak

TypeScript

  • 123