Skip to content

Latest commit

 

History

History
274 lines (189 loc) · 7.55 KB

breakout-typescript.md

File metadata and controls

274 lines (189 loc) · 7.55 KB

Typescript

This is a follow-up tutorial to the Breakout OOP project. The goal of this tutorial is to convert the Breakout OOP project from vanilla JS to TypeScript.

What is TypeScript? Type script is a type-safe version of JavaScript.

What are types and what does it mean to be type-safe? The values you assign to any variable is has a type. The same is true for the values returned from functions and the parameter values defined by functions. All of these things have a type.

JavaScript is a dynamic language, meaning any variable can hold any type. You can assign a variable a number on one line of code and a string on the next line, for example:

let x = 88
x = 'Hello World!' // No problem here!

This might seem like an advantage but in reality, it is a source of many common errors! In a type-safe language when a variable has been declared its type is also declared, and the type can not be changed! For example, the code below is written in TypeScript:

let x = 88
x = 'Hello World!' // Error can't assign type String to variable type number!

In the TypeScript example, the error is spotted before we run our program!

Why learn Typescript? TypeScript is the industry's best practice and is used professionally on almost every professional project over vanilla JS. Why? Because catching errors early makes more reliable products!

TypeScript does not run in a browser. Instead, your TypeScript files need to be converted to vanilla JavaScript first.

Implement TypeScript

To use TypeScript you need to implement a compiler. The instructions here use Webpack.

To follow this tutorial you need a project that uses Webpack. You'll use Webpack to compile your TypeScript and bundle your code as vanilla JS.

Follow these steps.

https://webpack.js.org/guides/typescript/

npm install --save-dev typescript ts-loader

Create:

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "node"
  }
}

Modify webpack.config.js

module.exports = {
  entry: './src/main.ts',
  module: {
    rules: [
      {
      test: /\.tsx?$/,
      use: 'ts-loader',
      exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

Notice main.js changed to ./src/main.ts.

You will have two sets of code. Your source code will be your TypeScript files, these are the files you will edit. You will also have your distribution code, which is code that is generated by the bundler and compiled from your TypeScript files.

Your source code will go in the src/ directory and the distribution code will go in the dist/ directory.

You will only edit the files in the src/ directory.

Typescript files use the .ts extension.

Make those folders now if you haven't.

Place all of your JS files in the src/.

Typescript files use the .ts file extension. Change the file names of all of the files in the src/ director so they end with the .ts file extension.

Great! You've just created all of your TypeScript files!

JavaScript is a subset of the TypeScript language. Any JS you write should work as TypeScript.

You aren't taking advantage of TypeScripts type safety. Go through your code and add types where needed. Here are some examples.

Follow the guide here: https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html

Below are some examples to get you started.

Variable types

let x: number = 120
let name: string = 'John Friend'
const ball: Ball = new Ball()

Notice that a class is a type!

Function types

This function takes two parameters a and b both are type numbers. It returns a number.

The second function doesn't return anything so the type is void!

function exampleFunc(a: number, b: number): number {
  return a + b
}

function otherFunc(): void {
  console.log('Hello')
}

Classes

Classes are their type!

A class will define properties and methods. Properties have a type, and methods will have parameter types and return types.

Here is an example of the Ball from Breakout.

Notice the properties and their types are declared inside the class but outside the constructor or other method. Notice the value is not set here!

Methods follow the same convention as functions.

Notice that the ctx is set to type any. If there's a situation where you don't have a type definition for something type any as a fallback.

class Ball extends Sprite {
  // Declare class properties here!
  radius: number
  dx: number
  dy: number

  constructor(x: number, y: number, radius = 10, color = 'blue') {
    super(x, y, radius * 2, radius * 2, color)
    // Properties declared above are initialized here
    this.radius = radius
    this.dx = 2
    this.dy = -2
  }

  move() {
    this.x += this.dx
    this.y += this.dy
  }

  render(ctx: any) { // Override
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.closePath();
  }
}

Classes are types

When defining a variable that stores an instance of a class the class is the type!

import Ball from './Ball'

// Notice the type here!
const ball: Ball = new Ball()

Imports and file extensions

When you convert to Typescript you will need to remove the file extension on your import statements.

This:

import Ball from './Ball.js'

Becomes:

import Ball from './Ball'

Array types

In Typescript Arrays are typed. This means that an array can only store one type. For example an array of numbers:

const nums: number[] = [1,2,3,4]

An array of string:

const names: string[] = ['A', 'B', 'C']

For an array of arrays the type might look like this:

const grid: number[][] = [[1,2,3], [4,5,6]]

Linting with TypeScript

Linting is a crucial step in maintaining code quality and consistency when working with TypeScript. TypeScript can be seamlessly integrated with popular linting tools like ESLint and TSLint. Here's how to set up linting for your TypeScript project:

  1. Install Dependencies:

    • Install ESLint and TypeScript if you haven't already.
      npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
      
  2. Configuration:

    • Create an ESLint configuration file (.eslintrc.js) in your project directory.
    • Configure it to use the TypeScript parser and TypeScript-specific rules:
      module.exports = {
        parser: "@typescript-eslint/parser",
        plugins: ["@typescript-eslint"],
        extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
      };
  3. Run Linter:

    • Use the eslint command to lint your TypeScript files:
      npx eslint your-file.ts
      

Linting helps catch common errors, enforces coding standards, and enhances code readability. You can also set up custom rules and integrate linting into your build process for real-time feedback.

Feel free to check out the TypeScript ESLint docs!

TypeScript docs

You'll need to refer to the TypeScript docs in some cases. Take a look at them here:

https://www.typescriptlang.org/docs/

Discussion

Answer these questions about TypeScript.

  • Q: What is TypeScript?
  • Q: What changes did the TypeScript linter ask you to make to the Break Out game?
  • Q: Did TypeScript improve your code?
  • Q: Write a for loop with TypeScript?