###### Table of Contents
- [[#Basic Types]]
- [[#Literal Types]]
- [[#Arrays]]
- [[#Generic Arrays]]
- [[#Tuples]]
- [[#Unions]]
- [[#Enums]]
- [[#Objects]]
- [[#Type Assertion]]
- [[#Functions]]
- [[#Return type inference]]
- [[#Interfaces]]
- [[#Interfaces with Functions]]
- [[#Interfaces with Classes]]
- [[#Types vs Interfaces]]
- [[#Generics]] ^dc20dd
- [[#With React]]
- [[#More info]]
To set up TypeScript in a project (creates a `tsconfig.json` file)
```zsh
tsc --init
```
### Syntax errors vs type errors
In JavaScript, any code with valid _syntax_ will run. In TypeScript, code must have valid _syntax_ and must _type check_. Only then will it run.
- JavaScript: syntax check ➞ execution.
- TypeScript: syntax check ➞ type check ➞ execution.
There are three categories of types in Typescript:
- **`Built-in`** types include number, string, boolean, undefined, null, and void.
- **`User-defined`** types include enum, array, interface, class, and tuple.
- the **`any`** type is a superset of all Typescript data types, and it is the loosest one available. It means that a variable can be of any type. Type checking is overridden when this type is used.
### Basic Types
```typescript
let id: number = 5
let company: string = 'ACME Corporation'
let isPublished: boolean = true
let x: any = 'Hello'
```
### Literal Types
In addition to basic types like `number` and `string`, every concrete number and every concrete string is also a type. For example, a variable of type `1` can only hold the number `1`. It can't hold `2`; that's a compile-time type error.
```typescript
let one: 1 = 1;
one; //➞ 1
let one: 1 = 2;
one; //➞ type error: Type '2' is not assignable to type '1'.
```
These are called _literal types_. For example, the type `1` above is a _literal number type_. We can combine _literal types_ with _unions_ to allow only certain values.
This seems like a strange feature at first, and most statically typed programming languages don't support it. However, it's very useful in practice and is used often in real-world TypeScript code.
```typescript
let oneOrTwo: 1 | 2 = 2;
oneOrTwo //➞ 2
let oneOrTwo: 1 | 2 = 3;
oneOrTwo //➞ type error: Type '3' is not assignable to type '1 | 2'.
type DatabaseType = 'mysql' | 'postgres' | 'oracle';
let dbType: DatabaseType = 'mysql';
dbType //➞ 'mysql'
```
`true` and `false` are also literal types. A variable of type `true` can never be `false`.
```typescript
let t: true = true;
t //➞ true
```
### Arrays
```typescript
let ids: number[] = [1, 2, 3]
let arr: any[] = [1, true, 'Hello']
```
#### Generic Arrays
In addition to array types written as `number[]`, there's another way to write them: `Array<number>`.
This syntax with angle brackets (`<` and `>`) shows up a lot in TypeScript. The `number[]` form only exists because many people find it more readable. An array is an array regardless of which way we write it.
```typescript
let numbers: number[] = [1];
let numbers2: Array<number> = numbers;
numbers2 //➞ [1]
```
Array types like `Array<number>` are an example of [[#Generics | generics]]. We can think of `Array` as a type with a "hole" in it. An array of numbers, `Array<number>`, fills the hole with the `number` type. An array of strings, `Array<string>`, fills the hole with the `string` type.
### Tuples
TypeScript supports tuples, which are arrays of fixed length. For example, `[number, number]` is a tuple of two numbers. It must be exactly two numbers; not one and not three. If the length doesn't match, it's a type error.
```typescript
let numbers: [number, number] = [1, 2];
numbers[0] //➞ 1
let person: [number, string, boolean] = [1, 'John', true]
person[1] //➞ 'John'
```
```typescript
let numbers: [number, number] = [1];
// type error: Type '[number]' is not assignable to type '[number, number]'. Source has 1 element(s) but target requires 2.
```
Tuples can have different types in each index. This is different from arrays, where every element must have the same type.
```typescript
let numberAndString: [number, string] = [1, 'a'];
numberAndString[1] //➞ 'a'
```
##### Tuple Array
```typescript
// Tuple Array
let employee: [number, string][]
employee = [
[1, 'John'],
[2, 'George'],
[3, 'Ringo'],
[4, 'Paul']
]
```
### Unions
```typescript
// Allow a variable to hold more than one type
let pid: string | number
pid = '20'
pid = 'twenty'
```
Many JavaScript functions take arguments that can be one of multiple types.
That example below might seem a bit strange. We can see that `cleveland` returns `44106`, which is a number. But we explicitly told the compiler that the function returns a `string | number`. The compiler doesn't try to find a "better" type than the one we provided. It only checks against the provided type:
```typescript
function getClevelandZipCode(): string | number {
return 44106;
}
let zip: number = getClevelandZipCode();
zip; //➞ type error: Type 'string | number' is not assignable to type 'number'.Type 'string' is not assignable to type 'number'.
```
### Enums
```typescript
// Allow for the creation of named constants
enum Direction1 {
Up,
Down,
Left,
Right
}
console.log(Direction.Up) //➞ 0
enum Direction1 {
Up = 1,
Down,
Left,
Right
}
console.log(Direction1.Down) //➞ 2
enum Direction2 {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right'
}
console.log(Direction2.Down) //➞ 'Down'
```
### Objects
```typescript
const user: {
id: number,
name: string
} = {
id: 1,
name: 'John'
}
// code above looks a little messy, so an alternative is to do:
type User = {
id: number;
name: string;
}
const user: User = {
id: 1,
name: 'John'
}
const users: Users[] = [] // define an array of products
```
### Type Assertion
```typescript
// type assertion explicity tells the compiler we want to treat an entity as a different type
let cid: any = 1
//two different syntaxes
let customerId = <number>cid
// or
let customerId = cid as number
```
### Functions
```typescript
function addNum(x: number, y: number): number {
return x + y
}
console.log(addNum(1, 2)) //➞ 3
function log(message: string | number): void {
console.log(message)
}
log('Hello') //➞ 'Hello'
```
#### Return type inference
Functions' return types can be inferred, which saves us from typing them out. As with all inference, the types still exist and are still enforced. Inference only means that the compiler can determine the types for us.
```typescript
function two() {
return 1 + 1;
}
two() //➞ 2
```
### Interfaces
```typescript
interface UserInterface {
// readonly property
readonly id: number,
name: string,
// optional property
age?: number
}
const user1: UserInterface = {
id: 1,
name: 'John'
}
```
#### Interfaces with Functions
```typescript
// interfaces with functions
interface MathFunc {
(x: number, y: number): number
}
const add: MathFunc = (x: number, y:number): number => x + y
const sub: MathFunc = (x: number, y:number): number => x - y
```
#### Interfaces with Classes
```typescript
// interfaces with classes
interface PersonInterface {
id: number
name: string
register(): string
}
class Person implements PersonInterface {
id: number
name: string
constructor(id: number, name: string) {
this.id = id
this.name = name
}
register() {
return `${this.name} is now registered.`
}
}
const brad = new Person(1, 'Brad Jones')
const mike = new Person(1, 'Mike Jordan')
console.log(brad.register) //➞ `Brad Jones is now registered`
// Subclass
class Employee extends Person {
position: string
constructor(id: number, name: string, position: string) {
super(id, name)
this.position = position
}
}
const emp = new Employee(3, 'Shawn', 'Developer')
console.log(emp.name) //➞ 'Shawn'
console.log(emp.register()) //➞ 'Shawn is now registered'
```
#### Types vs Interfaces
One of the key differences between an interface definition and a type definition is that *we cannot add new properties to a type, while an interface, on the other hand, can be extendable*.
Also, unlike an interface, the type alias can be used for other types, such as primitives, while an *interface declaration is always an object*.
```typescript
// types can be used with primitives and with unions
type Point = number | string
const p1: Point = 1
// you can't use an interface in that 👆🏾 way
```
### Generics
```typescript
// Generics are used to build reusable components
// <T> is a placeholder
function getArray<T>(items: T[]): T[] {
}
// the type is defined here (in the angle brackets)
let numArray = getArray<number>([1, 2, 3, 4])
let strArry = getArray<string>(['brad', 'john', 'derek'])
```
#### Generic Arrays
Array types like `Array<number>` are an example of _generics_. We can think of `Array`as a type with a "hole" in it. An array of numbers, `Array<number>`, fills the hole with the `number` type. An array of strings, `Array<string>`, fills the hole with the `string` type.
There's nothing special about arrays of numbers or arrays of strings. We can put any type in the hole, with no restrictions whatsoever.
```typescript
let numbers: number[] = [1];
let numbers2: Array<number> = numbers;
numbers2 //➞ [1]
let numbers: Array<number> = [1];
let numbers2: number[] = numbers;
numbers2 //➞ [1]
```
The array elements can be complex, as in arrays of arrays. This is the same array of arrays concept that you see in JavaScript. We're just writing its type down explicitly.
```typescript
let arrays: Array<Array<number>> = [[1, 2], [3, 4]];
arrays[1] //➞ [3, 4]
```
### With React
```jsx
// Header.tsx
export interface Props {
title: string
color?: string
}
const Header = (props: Props) => {
return (
<header>
<h1 style={{ color: props.color }}>{props.title}</h1>
</header>
)
}
// App.tsx
import Header from './Header'
function App() {
return (
<div className='App'>
<Header title='Hello World' color='red' />
</div>
)
}
```
### More info
[TypeScript Crash Course - Traversy](https://youtu.be/BCg4U1FzODs)
[TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
___
**Tags**: #typescript