TypeScript Crash Course

Developed and maintained by Microsoft. TypeScript is JavaScript with syntax for types. Similar to JavaScript, the difference is TypeScript is strict, especially to data type. TypeScript needs to compile first. It will produce JavaScript files for production.

We should master JavaScript before TypeScript. It is important. They use the same syntaxes, but TypeScript adds additional syntaxes to make it strict. You can visit JavaScript Crash Course the learn JavaScript first.

Prerequisites

I assume you already installed prerequisites from here, they are the text editor and NodeJS. Next is to install TypeScript. I suggest to install it globally via npm (NodeJS package manager), npm install -g typescript. You can verify it by tsc --version. Type tsc --help to show all information. Type tsc --init to create a tsconfig.json file. It will leave you a recommended config. It is to configure the TypeScript compiler, especially when in the editor, to remove errors in the editor that caused by conflicts with the JavaScript file. You can visit this page for more information.

Create a main.ts file. Run tsc --watch main.ts on the terminal. It will create a main.js file and recreate it every time it has change. You can play around with some examples below. Practice makes perfect.

Type

TypeScript is strict about data type. The variable can't changes its data type except any. Here are built-in type primitives; boolean, string, number, undefined, null, any, unknown, never, void, bigint, and symbol. In TypeScript, we can define a primitive type by a syntax type. I made examples of type to explain its rule.

Object Literal Type

1
2
3
4
5
6
7
8
9
10
11
type User = {
  name: string;
  role: "administrator" | "editor" | "author";
}

let user: User = {
  name: "John Doe",
  role: "administrator"
}

console.log(user);

With union |, we can define options for the value.

Tuple Type

1
2
3
4
5
6
7
8
9
type Post = [
  title: string,
  likes: number,
  createdAt: Date,
]

let post: Post = ["Lorem Ipsum", 0, new Date()];

console.log(post);

Tuple is a fixed array with its fixed data type.

Intersection Types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Author = User & { posts: Post[] }

let posts: Post[] = [
  post,
  ["The Magic Spell", 9, new Date()],
  ["The Magic Number", 12, new Date(2022, 3, 24)]
]
let author: Author = {
  name: "Harry Potter",
  role: "author",
  posts: posts,
}

console.log(author);

We can combine types by using &.

Type Indexing

1
2
3
4
5
6
7
8
type Posts = Author["posts"]

let featuredPosts: Posts = [
  ["TypeScript is awesome!", 100, new Date()],
  ["", 0, new Date()],
]

console.log(featuredPosts);

We can get the data type by indexing.

Type from Value

1
2
3
4
5
6
7
8
9
10
11
const setSlug = (slug: string): string => {
  return slug.toLowerCase().replace(" ", "-")
}

type Slug = ReturnType<typeof setSlug>

const createPost = (post: Post, slug: Slug): {post: Post, slug: Slug} => {
  return {post, slug}
}

console.log(createPost(post, setSlug(post[0])));

We can get the data type from the function by using ReturnType then assign it.

Mapped Types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
type Print<Type> = {
  [Property in keyof Type]: (value: Type[Property]) => void;
}

let printName = (value: string): void => {
  console.log(value);
}

let printRole = (value: "administrator" | "editor" | "author"): void => {
  console.log(value);
}

let printUser: Print<User> = {
  name: printName,
  role: printRole
}

printUser.name("John Cena")
printUser.role("editor")

We can create a mapped data type for functions. This feature is great for building libraries.

Conditional Types

1
2
3
4
5
6
7
8
9
10
11
12
type Administrator = { name: string, role: "administrator" }
type Editor = { name: string, role: "editor" }
type Moderator = Administrator | Editor
type IsAdministrator<Moderator> = Moderator extends { role: "administrator" } ? Moderator : never
type AdminModerator = IsAdministrator<Moderator>

let adminModerator: AdminModerator = {
  name: "Admin Moderator",
  role: "administrator"
}

console.log(adminModerator)

We can create a condition to reduce options for data types.

Interface

Interface is to describe the shape of objects. Common built-in objects; Date, Error, Array, Map, Set, Regexp, and Promise. In JavaScript and TypeScript, we can create templates for objects by using classes. Maybe I will make an article for that later.

Generics

1
2
3
4
5
6
7
8
9
10
11
12
13
type Role = "administrator" | "editor" | "author";

interface User<Role> {
  name: string;
  role: Role;
}

let user: User<Role> = {
  name: "John Doe",
  role: "administrator"
}

console.log(user);

This interface has the same function as the type above.

Extending Interface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface Post extends User<Role> {
  title: string;
  likes: number;
  createdAt: Date;
}

let post1: Post = {
  name: user.name,
  role: user.role,
  title: "Lorem Ipsum",
  likes: 0,
  createdAt: new Date()
}

console.log(post1);

The extends is for extending interface.

Intersection Interface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface OnlyPost {
  title: string;
  likes: number;
  createdAt: Date;
}

let post2: User<Role> & OnlyPost = {
  name: user.name,
  role: user.role,
  title: "Lorem Ipsum",
  likes: 0,
  createdAt: new Date(),
}

console.log(post2);

We also can extend or combine interfaces by using &.

Optional & Readonly Properties

1
2
3
4
5
6
7
8
9
10
interface StrictPost {
  title: string;
  likes?: number;
  readonly createdAt: Date;
}

let post3: StrictPost = {
  title: "Lorem Ipsum",
  createdAt: new Date()
}

The ? is to let the attribute to be empty or undefined. The readonly is to forbid value modification.

Interface with Parameters (Generics)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
type ParameterPost = {
  title: string,
  likes: number,
  createdAt: Date,
}

interface ParameteredPost<ParameterPost> {
  data: ParameterPost;
}

let parameteredPost: ParameteredPost<ParameterPost> = {
  data: {
    title: "Lorem Ipsum",
    likes: 0,
    createdAt: new Date()
  }
}

console.log(parameteredPost);

The interface can have parameters. The parameter is the data type. It is similar to the generic one above.

Closing

TypeScript is designed for the development of large applications. Strict to its data type, it is important to have when working with a big number of developers and features. So, the data can be consistent with its data type.

Especially on the front-end. We can also work with TypeScript for front-end development. Many libraries support TypeScript, such as Angular and React. Many companies migrated their front-end development to TypeScript. It is a demanded skill because of its benefit or features. You can get the examples above on here, https://github.com/aristorinjuang/ts-crash-course.

References

Related Articles