It allows to combine multiple types.
// 1️⃣ Object
type Admin = {
name: string;
priviledges: string[];
}
type Employee = {
name: string;
startDate: Date;
}
type ElevatedEmployee = Admin & Employee; // (*)
const el = ElevatedEmployee {
name: 'Suyeon',
priviledges: ['create-server'],
startDate: new Date()
};
// 2️⃣ Any value
type Combinable = string | number;
type Numeric = number | boolean;
type Universal = Combinable & Numeric; // (*)
Alternative
you can also implement it using interface
interface Admin {
name: string;
priviledges: string[];
}
interface Employee = {
name: string;
startDate: Date;
}
interface ElevatedEmployee extends Admin, Employee {}
When you want to implement different actions based on types(type checking).
1️⃣ typeof
type Combinable = string | number;
function add(a: Combinable, b:Combinable) {
if(typeof a === 'string' && typeof b === 'string') { // (*)
return a.toString() + b.toString();
}
return a + b;
}
2️⃣ property in obj
type Admin = {
name: string;
priviledges: string[];
}
type Employee = {
name: string;
startDate: Date;
}
type ElevatedEmployee = Admin & Employee;
type UnknownEmployee = Employee | Admin;
function printEmployee(emp: UnknownEmployee) {
if('priviledges' in emp) { // (*) if(emp.priviledges) not working!
console.log(emp.priviledges);
}
}
3️⃣ instanceof
interface
.class Car {
drive() {
console.log('driving...');
}
}
class Truck {
drive() {
console.log('driving a truck...');
}
loadCargo(amount: number) {
console.log('Loading cargo...' + amount);
}
}
type Vehicle = Car | Truck;
const v1 = new Car();
const v2 = new Truck();
function useVehicle(vehicle: Vehicle) {
vehicle.drive();
if(vehicle instanceof Truck) { // (*)
vehicle.loadCargo(1000);
}
// OR if('loadCargo' in vehicle)
}
4️⃣ Descriminated unions
interface Bird {
type: 'bird'; // (*) Literal type. Namining(type) is up to you.
flyingSpeed: number;
}
interface Horse {
type: 'horse';
runningSpeed: number;
}
type Animal = Bird | Horse;
function movingAnimal(animal: Animal) {
let speed;
switch(animal.type) { // (**)
case 'bird':
speed = animal.flyingSpeed;
break;
case 'horse':
speed = animal.runningSpeed;
break;
}
console.log(speed);
}
movingAnimal({ type: 'bird', flyingSpeed: 10 });
When you want to inform TS that a centain value is of a specific type.
!
tells typescript that it will never return null(we know it exists).HTMLElement
).<>
syntax or as
syntax.<input type="text" id="userName" />
/* Not working
const userName = document.querySelector('userName')!; // HTMLElement
userName.value = 'Suyeon';
*/
// 1️⃣ <> syntax
const userName = <HTMLInputElement>document.querySelector('userName')!;
// 2️⃣ as syntax
const userName = document.querySelector('userName')! as HTMLInputElement;
userName.value = 'Suyeon';
// with if statement
const userName = document.querySelector('userName');
if(userName) {
(userName as HTMLInputElement).value = 'Suyeon'
}
[property name's type]: value type
interface ErrorContainer {
[props: string]: string;
}
const errorBag: ErrorContainer = {
email: 'Not a valid email!',
userName: 'Must start with capital character!'
}
When you need to set function's return type with union types in order to use specific methods.
/*
addFunc return value is Combinable.
So when actual return value is string, typescript doesn't know.
Then you cannot use string method.
*/
type Combinable = string | number;
function addFunc(a: number, b: number): number; // (*)
function addFunc(a: string, b: string): string;
function addFunc(a: string, b: number): string;
function addFunc(a: Combinable, b:Combinable) {
if(typeof a === 'string' && typeof b === 'string') {
return a.toString() + b.toString();
}
return a + b;
}
const result = add('Suyeon', 'Kang');
result.split(' '); // working!
// const result = add('Suyeon', 'Kang') as string; Alternative
Optional chaining helps us to access safely to the data of nested object or nested property. If data is undefined, it will not continue. It is useful when fetching some data from server.
const fetchedData = {
id: 'u1',
name: 'Suyeon',
job: { title: 'chef', des: 'cooking' }
};
console.log(fetchedData?.job?.title); // (*)
// console.log(fetchedData.job && fetchedData.job.title); Alternative
if value is exactly null or undefined(not 0 or ''), then it use fallback.
const userInput = '';
const storedData = userInput ?? 'DEFAULT'; // (*)
// const storedData = userInput || 'DEFAULT'; Alternative(null, undefined, 0, '')