- Published on
 
Intro to TypeScript
- Authors
 
- Name
 - K N Anantha nandanan
 - @Ananthan2k
 
What is TypeScript?
- superset of JavaScript
 - adds static types to JavaScript
 - is compiled to JavaScript during the build process
- TS => typescript compiler => JS
 
 - all JavaScript is valid TypeScript
 
Is very useful since it catches many errors before they are discovered at runtime.
- recall all the edge cases we had to test out in our previous projects.
 
TypeScript CLI
Install globally:
npm install -g typescript
tsc CLI options
We can say...
tsc myFile.ts
And it will compile the file to JavaScript.
Now have access to tsc command. (TypeScript Compiler)
# uses default settings; .js file will have the same name as .ts file
tsc index.ts # produces index.js file
# compile to named destination file
tsc index.ts --outFile my-index.js # produces my-index.js
# add the watch flag to avoid having to manually trigger the compiler
tsc index.ts --watch # watches for changes to index.ts
# the target flag allows us to specify the version of JS we are compiling to
tsc index.ts --target es6 # compiles to es6 syntax JS
tsc --init # will create a tsconfig.json file in the current directory
# after initializing, running `tsc` will use the configuration specified in the file
tsc
Primitive Types
How do we add types to something?
- use the colon 
:after a variable name to specify its type 
const str: string = 'hello world'
const isLoggedIn: boolean = false
const num: number = 3.14
If we try to assign a value of the wrong type to a variable, TypeScript will throw an error.
let numTwo: number = 2
numTwo = 'hello' // error
// error TS2322: Type '"hello"' is not assignable to type 'number'.
- Assign multiple types to a variable using the 
|operator 
let numThree: number | string = 3
numThree = 'hello' // valid
numThree = true // error
// error TS2322: Type 'false' is not assignable to type 'string | number'.
Arrays
- use the 
[]syntax to specify an array of a certain type - arrays are just collections of a type
 - use the 
Array<type>syntax to specify an array of a certain type 
const arr: number[] = [1, 2, 3]
const arrTwo: Array<number> = [1, 2, 3]
arr.push(4) // valid
arr.push('hello') // error
Objects and Interfaces
- are a bit more complex than arrays
 - need to create an 
interfaceto specify the shape of the object 
An interface specifies the keys an object will have, and the type of the value associated with each key.
- we can put interfaces in a separate file and import them into other files
 
interface User {
  name: string
  age: number
  isLoggedIn: boolean
}
const user: User = {
  name: 'John',
  age: 30,
  isLoggedIn: true,
}
- this is like adding your own type definitions (this is known as a interface)
 
Another example:
interface Author {
  name: string
  penName: string
  isActive?: boolean // optional params are marked with a question mark (?)
  writeBook: (title: string) => boolean // function types need the type of the arguments and the return type
}
const curtis: Author = {} // error!
// error TS2741: Property 'name' is missing in type '{}' but required in type 'Author'.
const person: Author = {
  name: 'Curtis',
  penName: 'Curtis',
  writeBook: (title: string) => true,
}
- the 
?afterisActiveindicates that the property is optional - when using an interface to define a function, the function type needs to be specified
- need to specify the type of the arguments and the return type
 
 
const agatha: Author = {} // error!
const stephen: Author = {} as Author // no error
Hack: To force TypeScript to accept a type, use the
askeyword
Can create the interface a different way:
const user: { name: string; age: number } = {
  name: 'Curtis',
  age: 30,
}
Array of objects:
const users: User[] = []
users.push(user)
- it is common to place a 
iin front of the interface name 
Functions
- specify the type of the 
argumentsand thereturntype of a function 
const sayHello = (name: string): string => {
  return `Hello ${name}`
}
sayHelloaccepts astringas an argument and returns astring
Void
- if a function does not return anything, we must use the 
voidtype 
const noReturn = function (name: string): void {
  console.log(name)
}
Promises
- a function that returns a 
Promise(orasync) must wrap the return value in thePromisetype 
const returnsPromise = (name: string): Promise<string> => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(name), 1000)
  })
}
const returningPromise2 = (num: number): Promise<number> => {
  return new Promise((res) => {
    res(num * 2)
  })
}
If you passed no arguments into the function, it would be an error.
returnsPromise() // error
Type Inference
- TypeScript can infer the type for us, then we don't need to specify it
 - docs: Type Inference
 
No need to specify string type:
const name = 'John'
Works with interfaces too:
interface User {
  username: string
  password: string
}
// logInUser accepts a User type
const logInUser = (user: User): boolean => {
  return user.username === 'johnstamos'
}
// no type specified for potentialUser
const potentialUser = {
  username: 'johnstamos',
  password: 'pass123',
}
// no problem passing potentialUser to logInUser
const loggedIn = logInUser(potentialUser)
If we try to pass a user that doesn't have the correct properties, TypeScript will throw an error:
const potentialUser = {
  username: 'johnstamos',
  password: 'pass123',
  age: 30, // error!
}
const isLoggedIn = logInUser(potentialUser)
// error!
// error TS2345: Argument of type '{ username: string; }' is not assignable to parameter of type 'User'.
// Property 'password' is missing in type '{ username: string; }' but required in type 'User'.
Methods
- same syntax as functions
 
interface IUser {
  username: string
  password: string
  drinkLiquid: (fluid: string) => boolean
}
const curtis: IUser = {
  username: 'curtis',
  password: 'pass123',
  drinkLiquid: (fluid: string) => {
    return true // needs to return a boolean because of the return type in the interface
  },
}
Callbacks
const higherOrderFunction = (callback: (num: number) => number): number => {
  return callback(2)
}
Generics
- are interfaces when some or all types are not known at the time of definition time
- instead, they are passed in as arguments when the interface is used
 
 - allow us to pass a variable to a type
 - we specify the variable using 
<and> 
interface Container<Type> {
  title: string
  contents: Type
}
const numContainer: Container<number> = {
  title: 'number container',
  contents: 7,
}
const stringContainer: Container<string> = {
  title: 'string container',
  contents: 'hello',
}
- It is common to shorten 
Typeto simplyT 
interface Container<T> {
  contents: T
}
Compiling TypeScript tsconfig.json
- 
we have seen we can call
tscto compile our TypeScript files - 
create the
tsconfig.jsonfile 
tsc --init
creates a
tsconfig.jsonfile in the current directory. You should do this in the root file.
- modules
- want to preserve import/export syntax use 
es6 
 - want to preserve import/export syntax use 
 - root directory
- may make it the "./src" directory
 
 - output directory
- may make it the "dist" directory
 
 - allow JS files
- set to 
true - need to turn this on to allow JS files to be compiled
 
 - set to 
 - emit
- where does it go to?
 - IMPORTANT 
outFileis where the compiled JS file will go.- will create ONE file
 
 - more common 
outDiris where the compiled JS file will go.- will create a directory with the compiled JS file
 
 
 
TSC --watch
watch for changes in the file and recompile
tsc --watch
Will go on in the background. Even in react, you can use this to compile your TS files.
Useful Resources
- TS site
 - TS Compiler Options
 - TS in 5 minutes
 - TS Playground: TS Playground