TypeScript has an unusual relationship with JavaScript. TypeScript offers all of JavaScript’s features, and an additional layer on top of these: TypeScript’s type system.
For example, JavaScript provides language primitives like string
and number
, but it doesn’t check that you’ve consistently assigned these. TypeScript does.
This means that your existing working JavaScript code is also TypeScript code. The main benefit of TypeScript is that it can highlight unexpected behavior in your code, lowering the chance of bugs.
This tutorial briefly overviews TypeScript, focusing on its type system.
Table of Contents
- 1. Prerequisites
- 1.1 Installing TypeScript
- 1.2 Understanding TypeScript Syntax
- 1.3 Types by Inference
- 1.4 Defining Types
- 1.5 Generics
- 1.6 Enums
- 1.7 Classess
- 1.8 HTML Types
- 2. Conclusion
- 3. Resources
Prerequisites
You’ll need a working understanding of JavaScript and NodeJS installed.
Installing TypeScript
Before diving into TypeScript code, you'll need to install it. If you have Node.js installed, you can install TypeScript globally via npm:
npm install -g typescript
To compile TypeScript code, use the tsc
command and create files as .ts
extensions.
tsc filename.ts
Understanding TypeScript Syntax
When i was initially trying out TypeScript due to the existing developer's hype and the fact that most tutorials I was looking at were in TypeScript, I was overwhelmed by the amount of errors it throws around. While TypeScript code is just like plain old JavaScript, it comes with type annotations that must be respected.
Types by Inference
TypeScript knows the JavaScript language and will generate types for you in many cases. For example in creating a variable and assigning it to a particular value, TypeScript will use the value as its type.
let helloWorld = "Hello World";
// let helloWorld: string
Defining Types
You can use a wide variety of design patterns in JavaScript. However, some design patterns make it difficult for types to be inferred automatically (for example, patterns that use dynamic programming). To cover these cases, TypeScript supports an extension of the JavaScript language, which offers places for you to tell TypeScript what the types should be.
For example, to create an object with an inferred type which includes name: string
and id: number
, you can write:
const user = {
name: "Hayes",
id: 0,
};
Typescript will help you catch development errors earlier on by preventing you from assigning wrong types to a value. For example, assigning a number to the user name variable.
You can explicitly describe this object’s shape using an interface
declaration:
interface User {
name: string;
id: number;
}
You can then declare that a JavaScript object conforms to the shape of your new interface
by using syntax like : TypeName
After a variable declaration:
const user: User = {
name: "Hayes",
id: 0,
};
If you provide an object that doesn’t match the interface you have provided, TypeScript will warn you:
interface User {
name: string;
id: number;
}
const user: User = {
username: "Hayes",
| Object literal may only specify known properties,
and 'username' does not exist in type 'User'.
id: 0,
};
Types can also be passed to function props using Interface or type declarations to ensure a function always receives the right data types.
function add(a: number, b: number): number {
return a + b;
}
But hold on, what are Interfaces and Types?
In TypeScript, you can use Interfaces and Types to define the structure objects, which makes the code easier to maintain.
const car: { type: string, model: string, year: number } = {
type: "Toyota",
model: "Corolla",
year: 2009
};
//you can use type to structure the data
type Car = {
type: string;
model: string;
year: number;
};
Defining Types makes it easier to export and reuse a common datatype. While Interface and Types might look similar, typescript Interface can be extended and merged. If you declare the same interface multiple times, TypeScript will merge them into one. This enhances inheritance and helps us maintain the DRY principle.
interface User {
firstName: string;
lastName: string;
email: string;
}
interface StaffUser extends User {
roles: string[];
department: string;
}
On the other hand, Types Ccn defines any kind of type, not just object shapes. You can use type
it to define unions, primitives, tuples, function signatures, etc. It’s more versatile in comparison to interface
.
//union types
type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
function getLength(obj: string | string[]) {
return obj.length;
}
Generics
Generics provide variables to types. A common example is an array. An array without generics could contain anything. An array with generics can describe the values that the array contains.
type StringArray = Array<string>;
//this array can only contain string values
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;
Enums
An enum is a special "class" that represents a group of constants (unchangeable variables).
Enums come in two flavors string
and numeric
. Numeric enums start at zero and autoincrement, although users can assign them values. I have found enums very useful when setting the database to restrict the available options.
For example:
enum CardinalDirections {
North,
East,
South,
West
}
This enum ensures that a user cannot create a CardinalDirection that is not North, East, South, or West since the datatype will be invalid. Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases.
Classess
Typescript enhances classes by adding optional types and more powerful inheritance. This ensures that each new instance of the class adheres to the type definitions.
For example
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): void {
console.log(`${this.name} makes a sound.`);
}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
makeSound(): void {
console.log(`${this.name} barks.`);
}
}
let dog = new Dog('Rex');
dog.makeSound(); // Rex barks.
HTML Types
One of the major challenges that you will face with Typescript is HTML types, which are often unknown to you. For example, passing event
to a handleFormSubmit
function will often return an error if you do not specify the type of the event as SubmitEvent
.
HTMLElement
Is the base interface for all HTML elements. It contains common properties and methods shared by most HTML elements, such as id
, className
, innerHTML
, and more.
For Example
let element: HTMLElement = document.getElementById('myElement')!;
element.innerHTML = "Hello, world!";
Common Specific Element Types:
HTMLDivElement
: Represents an<div>
element.HTMLInputElement
: Represents an<input>
element (text fields, checkboxes, etc.).HTMLButtonElement
: Represents an<button>
element.HTMLFormElement
: Represents an<form>
element.HTMLAnchorElement
: Represents an<a>
(anchor) element.HTMLImageElement
: Represents an<img>
element.
Luckily, if you use frameworks such as React, You can import the types or they are auto-inferred for you. This will help ensure Typescript does not scream at you pretending not to know what an onChange
event on a form input is.
Conclusion
For developers coming from a JavaScript background, TypeScript can feel both familiar and foreign. It brings a lot of benefits to the table, particularly in large, complex applications where maintainability and catching bugs early are critical.
That said, it also introduces complexity and might not be necessary for smaller projects. The best way to decide if TypeScript is right for you is to try it out—start small, see how it fits into your workflow, and evolve from there.
Tutor Juliet
Published on
👏 👏
tech girl
Published on
Thanks for this comprehensive guide. My favorite type is any 😃
Tech Wizard
• Oct 31, 2024