Learn Typescript in 5minutes

The best way to learn typescript is to start using it. Take a .js file and rename it to .ts. (if it has react JSX in it, name it .tsx instead.)

From there, just fix the red squigglies.

“But how?”

Step 1. Read this page: Ts basics. This is a great primer. Don’t try to study this page. Just read thru to get an idea and come back to it later.

Next open a project, and start changing .js files to .ts. Use the docs or ask Perplexity to explain it to you. If you provide perplexity with a snippet and the error message + a question, it does a reasonably good job at telling you whats wrong and it might even link your some more resources.

Best Practice Examples - js vs ts

Below are some condensed snippets to help you move your code from js to ts.

Variables

let value = 1
let arr = []
arr.push(value)
let value = 1
// ts can't figure out that you want an array of numbers, so we have to be explicit here
let arr: number[] = []
arr.push(value)

Generally speaking, you should avoid adding types when type inference has got your back.

Doing things like this is redundant and gets old fast.

let num: number = 1

Functions

// js
function myFunc(value) {
  return value + 2
}
const myArrow = (value) => value + 2
// ts
function myFunc(value: number): number {
  return value + 2
}
const myArrow = (value: number): number => value + 2
//                                ^? this type, is the return of the function.
//                    it is optional, since ts can "figure out" the return type based on what you return
//                    this is whats called "type inference"

Generics basics

In typescript you’ll often see <> being used after types/functions. These are called Generics. They’re essentially a way to pass types, instead of values.

I would avoid making custom generics until you’re more familiar with the basics, but heres what you do need to know.

The best way to show you how generics work, is to show you some code of how you would make use one. You won’t have to do this part yourself, but this should help explain the next snippet.

function identity<T>(value: T) {
  return value
}
 
// or as an arrow function
const identity = <T>(value: T) => value

In both cases we’ve got an identity function that returns the value you pass in. This function can be used just like any other function.

identity("Hello there.")

If you plop this into an editor, you won’t get any errors. You can pass in any type you want and you won’t get errors.

Now lets try using the generic

identity<string>(1)

This on the other hand will give you an error.

Argument of type `number` is not assignable to parameter of type `string`.

We’ve effectively constrained what kind of value we can pass into the identity function.

“How is this useful?” Stay tuned.

Objects

const obj = {}
obj.name = "sam"

With objects, this is where you start to change how you design your code.

In javascript we can easily just not specify that obj will have name (but we then won’t get suggested that name might be there).

In typescript, we have to state all the keys up front and provide them with default values.

In the long run this is a better practice, because this cuts out a lot of if (obj.name) /* do something with obj */ type of code (usually called “defensive programming”).

const obj: { name: string } = { name: "" }
obj.name = "sam"

This can be cleaned up a bit by moving the type to a type.

type MyObject = { name: string }
const obj: MyObject = { name: "" }
obj.name = "sam"

types just like functions/variables can be exported and imported.

Note, typescript have types and interfaces. They’re pretty similar but interfaces have some extra, non-intuitive features, making them more error prone. I would recommend avoiding them for the most part.

React Component prop types

If you’re using propTypes, you can throw those away. Typescript does what that library does and better.

If you’re not using the prop-types package, skip down to the typescript snippet

// js
import React from 'react
import PropTypes from 'prop-types';
 
const MyComponent = ({ name }) => {
  return <div>Hello, {name}!</div>
}
 
MyComponent.propTypes = {
  name: PropTypes.string.isRequired
}
// ts
import React, FC from 'react
type Props = {
  name: string
}
const MyComponent: FC<Props> = ({ name }) => {
  return <div>Hello, {name}!</div>
}

FC is a type just like Props, but FC accepts a generic much like identity from earlier

In both these snippets if name isn’t provided, you’ll get a compile error. This is because name is required.

If instead you wanted it to be optional you would do this:

// ts
import React, FC from 'react
type Props = {
  // question mark denotes that name is optional.
  // Its equivalent to `name: string|undefined`
  name?: string
}
const MyComponent: FC<Props> = ({ name }) => {
  return <div>Hello, {name ?? 'World'}!</div>
}

In react, its best practice to use Arrow functions for components, since “traditional” functions don’t have access to FC.

This is the equivalent in using traditional functions:

// ts
function MyComponent(props: Props): JSX.Element {}

Heres some Resources: