TypeScript Core Concepts Explained for Beginners
Tags: webdev, javascript, beginners, tutorial
Published: 2024-02-15 23:15:33

TypeScript is a popular programming language that extends JavaScript with static typing. Static typing means that the type of a variable cannot be changed at any point in a program. This can prevent many common bugs and errors, and also make the code more readable and maintainable.

In this blog post, I will explain some of the core concepts of TypeScript, such as types, interfaces, generics, type casting, and more. By the end of this post, you will have a better understanding of what TypeScript can do and how to use it in your projects.

## Types
One of the main features of TypeScript is that it allows you to annotate your variables and functions with types. For example, you can declare a variable as a string, a number, a boolean, an array, an object, or any other type that TypeScript supports.

```js
// Declare a string variable
let name: string = "Alice";

// Declare a number variable
let age: number = 25;

// Declare a boolean variable
let isMarried: boolean = false;

// Declare an array of numbers
let scores: number[] = [90, 80, 70];

// Declare an object with properties
let person: {name: string, age: number, isMarried: boolean} = {
  name: "Alice",
  age: 25,
  isMarried: false
};
```

Type annotations help TypeScript to check the validity of your code at compile time. For example, if you try to assign a string to a number variable, TypeScript will give you an error.


```js
// This will cause an error
age = "twenty-five";
```

TypeScript also supports some special types, such as any, unknown, void, null, and undefined. The any type means that the variable can have any value, and TypeScript will not check its type. The unknown type is similar to any, but it requires you to explicitly cast it to another type before using it. The void type means that the function does not return any value. The null and undefined types represent the absence of a value.


```js
// Declare a variable of any type
let anything: any = "hello";
anything = 42;
anything = true;

// Declare a variable of unknown type
let something: unknown = "world";
something = 99;
something = false;

// Cast an unknown variable to a string
let str: string = something as string;

// Declare a function that returns void
function sayHello(name: string): void {
  console.log("Hello, " + name);
}

// Declare variables of null and undefined types
let nothing: null = null;
let missing: undefined = undefined;
```

## Interfaces

Interfaces are another way to define the shape of an object in TypeScript. They are similar to types, but they can be reused and extended by other interfaces or classes. For example, you can define an interface for a person, and then use it to declare a variable or a function parameter.

TypeScript
```js
// Define an interface for a person
interface Person {
  name: string;
  age: number;
  isMarried: boolean;
}

// Declare a variable of type Person
let alice: Person = {
  name: "Alice",
  age: 25,
  isMarried: false
};

// Declare a function that takes a Person as an argument
function greet(person: Person): void {
  console.log("Hello, " + person.name);
}
```

Interfaces can also have optional properties, which are marked with a question mark. For example, you can define an interface for a car, and make some of the properties optional.

TypeScript
```js
// Define an interface for a car
interface Car {
  model: string;
  year: number;
  color?: string; // optional property

TypeScript

// Define an interface for a car
interface Car {
  model: string;
  year: number;
  color?: string; // optional property
  owner?: Person; // optional property
}

// Declare a variable of type Car
let myCar: Car = {
  model: "Toyota",
  year: 2020
};

// You can also assign values to the optional properties
myCar.color = "red";
myCar.owner = alice;
```

## Generics

Generics are a way to make your code more reusable and flexible by allowing you to work with different types of values. For example, you can define a generic function that can accept and return any type of value, as long as it matches the type parameter.

TypeScript
```js
// Define a generic function that swaps the values of two variables
function swap<T>(a: T, b: T): [T, T] {
  return [b, a];
}

// Call the function with different types of arguments
let [x, y] = swap<number>(1, 2); // x = 2, y = 1
let [a, b] = swap<string>("hello", "world"); // a = "world", b = "hello"
let [p, q] = swap<Person>(alice, bob); // p = bob, q = alice
```

You can also define generic interfaces, classes, and types, and use them to create more specific types. For example, you can define a generic interface for a stack, and then use it to create a stack of numbers or a stack of strings.


```js
// Define a generic interface for a stack
interface Stack<T> {
  push(item: T): void;
  pop(): T;
  isEmpty(): boolean;
}

// Define a class that implements the Stack interface
class ArrayStack<T> implements Stack<T> {
  private items: T[];

  constructor() {
    this.items = [];
  }

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T {
    return this.items.pop();
  }

  isEmpty(): boolean {
    return this.items.length === 0;
  }
}

// Create a stack of numbers
let numberStack: Stack<number> = new ArrayStack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
console.log(numberStack.pop()); // 3
console.log(numberStack.pop()); // 2
console.log(numberStack.pop()); // 1

// Create a stack of strings
let stringStack: Stack<string> = new ArrayStack<string>();
stringStack.push("hello");
stringStack.push("world");
stringStack.push("!");
console.log(stringStack.pop()); // !
console.log(stringStack.pop()); // world
console.log(stringStack.pop()); // hello
```

## Type Casting

Type casting is a way to tell TypeScript that you know the type of a value better than it does. For example, if you have a variable of type any or unknown, you can cast it to a more specific type, such as string or number.

There are two ways to perform type casting in TypeScript: using the as keyword, or using angle brackets. For example, you can cast a variable of type any to a string using either of these methods.

```js
// Declare a variable of type any
let input: any = "42";

// Cast it to a string using the as keyword
let strInput: string = input as string;

// Cast it to a string using angle brackets
let strInput2: string = <string>input;
```

Type casting can be useful when you are working with values that come from external sources, such as user input, API responses, or DOM elements. For example, you can cast a DOM element to a specific type, such as an HTML input element, and access its properties and methods.


```js
// Get a DOM element by its id
let element = document.getElementById("my-input");

// Cast it to an HTML input element
let inputElement = element as HTMLInputElement;

// Get the value of the input element
let inputValue = inputElement.value;
```

## Conclusion

In this blog post, I have explained some of the core concepts of TypeScript, such as types, interfaces, generics, and type casting. These concepts can help you write more robust and maintainable code, and avoid common errors and bugs.