Typescript Basic Learning
In this journal, I wanted to grasp a quick overview about the understanding of Typescript to support my Angular learning.
In general, Typescript adds static typing
to JavaScript because JS is dynamic typed.
Installing and using Typescript
npm install typescript --save-dev
To ensure everyone using the same version of the language, use the following commands
npx tsc
Basically, the command npx tsc
will compile the *.ts
to *.js
. Also, after installing typescript, I could see error hint in my VS Code.
npx tsc with-typescript.ts
In vanilla JS, we used to implement code like this
function add(a, b) {
return a + b;
}
var result = add(2, 5);
console.log(result);
In Typescript, we can strengthen the type checking for parameter before passing them into the function like this.
function add(a: number, b: number) {
return a + b;
}
const result = add(2, 5);
console.log(result);
Basic Typescript
// Primitives: number, string, boolean
// More complex types: arrays, objects
// Function types, parameters
// Primitives
let age: number;
age = 12;
let userName: string | string[];
userName = 'Max';
let isInstructor: boolean;
isInstructor = true;
// More complex types
// array type
let hobbies: string[];
hobbies = ['Sports', 'Cooking'];
// object type
type Person = {
name: string;
age: number;
};
let person: Person;
person = {
name: 'Max',
age: 32,
};
// person = {
// isEmployee: true
// };
let people: Person[];
// Type inference
let course: string | number = 'React - The Complete Guide';
course = 12341;
// Functions & types
function addNumbers(a: number, b: number) {
return a + b;
}
function printOutput(value: any) {
console.log(value);
}
// Generics
function insertAtBeginning<T>(array: T[], value: T) {
const newArray = [value, ...array];
return newArray;
}
const demoArray = [1, 2, 3];
const updatedArray = insertAtBeginning(demoArray, -1); // [-1, 1, 2, 3]
const stringArray = insertAtBeginning(['a', 'b', 'c'], 'd');
// updatedArray[0].split('');
class Student {
// firstName: string;
// lastName: string;
// age: number;
// private courses: string[];
constructor(
public firstName: string,
public lastName: string,
public age: number,
private courses: string[]
) {}
enrol(courseName: string) {
this.courses.push(courseName);
}
listCourses() {
return this.courses.slice();
}
}
const student = new Student('Max', 'Schwarz', 32, ['Angular']);
student.enrol('React');
// student.listCourses(); => Angular, React
// student.courses => Angular, React
interface Human {
firstName: string;
age: number;
greet: () => void;
}
let max: Human;
max = {
firstName: 'Max',
age: 32,
greet() {
console.log('Hello!');
},
};
class Instructor implements Human {
firstName: string;
age: number;
greet() {
console.log('Hello!!!!');
}
}
Note:
// This is the array of type people
let people = {
name: string;
age: number;
}[];
// union type
let course: string | number = 'React - The Complete Guide';
What is interface?
- Interface is an object type definitions.
- Can add method into its structure.
- Can be implemented by classes
Why do we use the interface
keyword when we can achieve the same with the type
keyword?
- The reason is that an interface can be implemented by classes, thereby enforcing that classes adhere to the structure defined by the interface. -> Typescript will show error hints if we don’t implement the requirements in the interface.
- When working on applications developed by multiple developers, using interfaces can ensure that classes written by different developers conform to a specific structure when needed.
- The interfaces are more suitable for declaration merging and extending, whereas types are often preferred for union types and more complex type transformations. (see explanation)
Example:
- Using
interface
interface Shape {
calculateArea(): number;
}
class Circle implements Shape {
radius: number;
constructor(radius: number) {
this.radius = radius;
}
calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
}
In this example, the Shape
interface defines a structure with a method calculateArea()
. The Circle
class implements this interface, ensuring that it provides an implementation for the calculateArea
method.
- Using
type
:
type Shape = {
calculateArea(): number;
};
class Circle implements Shape {
radius: number;
constructor(radius: number) {
this.radius = radius;
}
calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
}
While using type
is possible, it lacks the explicit contract enforcement that an interface
provides. With interface
, you explicitly state that a class must implement certain methods, adding a level of clarity and enforcing the expected structure.
In the examples I provided, the code structures with interface
and type
are indeed very similar. In many cases, both interface
and type
can be used interchangeably to define object shapes in TypeScript. The choice between them often depends on specific use cases and personal or team preferences.
Declaration Merging and Extending with Interface
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: string;
}
const employee: Employee = {
name: "John",
age: 30,
employeeId: "EMP123"
};
In this example, we use an interface to define a Person
, and then we extend it to create an Employee
interface. This allows us to reuse the properties from Person
in Employee
and add the employeeId
property.
Union Types and Complex Type Transformations with Type:
type Status = "Pending" | "Approved" | "Rejected";
type NumericStatus = {
[K in Status]: number;
};
const statusCount: NumericStatus = {
Pending: 5,
Approved: 10,
Rejected: 2
};
Here, we use a type
to create a Status
type representing a union of string literals. Then, we use another type to create NumericStatus
, which transforms the union into an object where each status has a corresponding numeric value. This showcases the use of type for more complex type transformations.
In summary, while interface
is often used for declaration merging and extending, type
is flexible for creating union types and performing more intricate type transformations. Keep in mind that the choice between them can depend on the specific requirements of your code.
Compile All the Typescript files in one go
Need to add the typescript config file
npx tcs --init
What this does is it adds a tsconfig.json file. However, keep in mind that, when working with Angular, we probably do not need to run this command. This is just for the purpose of learning or running standalone project without Angular.
Strict mode
- Strict type checking
- Example: values are not able to infer the type. Need to explicitly set a type for those.
Resources
- https://www.typescriptlang.org/
- https://www.udemy.com/course/the-complete-guide-to-angular-2/learn/lecture/26105546#overview
- https://learnxinyminutes.com/docs/typescript/