TypeScript basics
Basic types
boolean\
const isLoading: boolean = true;
string\
const message: string = "Hello World!";
number\
const year: number = 2022;
const exp: number = 2.718;
array There are some ways to declare an array
const nums: number[] = [1, 2, 3, 4, 5]; // only numbers
const products: Array<string> = ["bread", "milk"]; // only strings
const someValues: [string, boolean] = ["ts", true]; // only 1 string and 1 boolean
any Allows to disable type checking, as a result the variable can dynamically change it's type. Avoid
any
in your code.
let value: any = "this is string";
value = 107;
value = false;
value = [1, 2, "a", "b", true];
Custom types and interfaces
Type Aliases Good for describing types in simple objects or for variables that may have more than one type.
type Animal = {
name: string;
age: number;
};
const animal: Animal = {
name: "Fluffy",
age: 4,
};
// extending a type
type Cat = Animal & {
color: string;
};
// value with 2 types
type ID = string | number;
const userId: ID = 239053;
const itemId: ID = "A934VL";
Interfaces An interface declaration is another way to name an object type. Interfaces support a more convenient extension and are used more often.
interface IPerson {
firstName: string;
lastName?: string; // an optional parameter
gender: "female" | "male"; // only certain values
isMarried: boolean;
}
//Extending an interface
interface IWorker extends IPerson {
job: string;
}
const someone: IWorker = {
firstName: "Alex",
gender: "male",
isMarried: true,
job: "engineer",
};
Functions
Basic usage We can describe the types of function arguments as well as the return value
// type "void" means that our function does not return anything
function logInfo(name: string, age: number): void {
console.log(`My name is ${name}, I'm ${age} y.o.`);
}
// Arrow function
const square = (x: number): number => x * x;
Default arguments When default parameters are specified, their types are automatically determined by the passed values
function getNumbers(max: number = 99, min = 1): void {}
Optional arguments\
function greeting(name?: string): void {
if (name) {
console.log(`Welcome, ${name}!`);
} else {
console.log(`Welcome, annonymous user!`);
}
}
Unlimited arguments You can describe an indefinite number of arguments of the same type using spread operator
const logValues = (x: number, ...values: string[]): void => console.log(x, ...values);
logValues(77, "one", "two", "three", "...");
Function type Use function type to describe methods
interface IService {
calcSum: (a: number, b: number) => number;
getBalance: () => string;
sendFeedback: (mes: string) => void;
}
Classes
Modifiers Various modifiers allow you to define the scope of variables and methods
class Example {
constructor(a: number, b: number) {
this.a = a;
this.b = b;
}
/* prevents assignments to the field outside
of the constructor */
readonly a: number;
/* visible only inside classes inherited from
the current class (not from outside) */
protected b: number;
/* visible only inside current class
(not from inherited and outside) */
private secret = "hello";
alert = () => {};
}
Extending a class Classes can easily be extended by adding new variables/methods. This also supports overriding methods, but in a way that ensures backward compatibility.
class NewExmaple extends Example {
constructor(a: number, b: number, c: number) {
super(a, b);
this.c = c;
}
c: number;
alert(name?: string) {
console.log(`Hello ${name}`);
}
}
Abstract classes Abstract classes/methods do not allow you to create instances, but only serve for expansion
abstract class Somebody {
hello(): void {
console.log("Hello!");
}
}
class User extends Somebody {
introduce(): void {
console.log("I am User!");
}
}
const user = new User();
user.hello(); // "Hello!"
Interface implementation Interfaces can be used to describe classes
interface ITest {
value: string;
getNumber: () => number;
}
class Test implements ITest {
value = "test";
getNumber = () => 7;
}
Enums
Numeric enums Enums allow to define a set of named constants. Numeric enums automatically assign numbers to named constants.
enum Roles {
user, // Roles.user = 0
moderator, // Roles.moderator = 1
admin, // Roles.admin = 2
}
enum Services {
GitHub = 10, // Services.Github = 10
Google, // Services.Google = 11
Amazon, // Services.Amazon = 12
}
String & mixed enums\
enum Bool {
yes = "YES",
no = "NO"
}
enum Server {
host = "server.com"
port = 5432
}
Generics
Basic usage Generics allows to create a component that can work over a variety of types rather than a single one
function test<T>(value: T): T {
return value;
}
// "T" will be replaced by the type we specified
test<string>("Hello World");
test<number>(2022);
test<boolean>(true);
Type checking You can safely use type checking with the
typeof
operator to execute the appropriate logic
function logger<T>(value: T): void {
if (typeof value == "string") {
// we are pretty sure that only strings will get here
console.log(value.toLocaleUpperCase());
// therefore, we can use string methods
} else if (typeof value == "number") {
console.log(value.toFixed(2));
} else {
console.log(`${value} has the ${typeof value} type`);
}
}
logger<string>("Hello World"); // "HELLO WORLD"
logger<number>(2022); // 2022.00
logger<boolean>(true); // "true has the boolean type"
Multiple generics You can pass multiple generics, for example, to describe different input and output types in functions
interface IService {
process: <T, S>(data: T) => S;
}
Extending generic type\
interface IValue {
info: string;
}
function test<T extends IValue>(value: T): T {
console.log(value.info);
return value;
}
Last updated