Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
menu
  1. Home
  2. /Web Development
  3. /Typescript
  4. /Enums
Your Progress0%
0 of 30 completed

TypeScript Topics

Getting Started

  • What is TypeScript?
  • TypeScript vs JavaScript
  • Setting Up TypeScript
  • Your First TypeScript Program

Basic Types

  • Primitive Types
  • Arrays and Tuples
  • Objects and Type Aliases
  • Enums
  • Any, Unknown, and Never

Functions & Interfaces

  • Function Types and Signatures
  • Interfaces
  • Optional and Default Parameters
  • Function Overloading

Advanced Types

  • Union and Intersection Types
  • Type Guards and Narrowing
  • Literal Types
  • Type Assertions and Casting

Generics

  • Introduction to Generics
  • Generic Constraints
  • Utility Types

Classes & OOP

  • Classes and Constructors
  • Access Modifiers
  • Inheritance and Polymorphism
  • Abstract Classes and Interfaces

Practical TypeScript

  • Working with Modules
  • TypeScript with React
  • Async/Await and Promises
  • Working with APIs and JSON
  • Type Declarations and DefinitelyTyped
  • TypeScript Best Practices

Enums

Creating named constants with enumerations

Enums (enumerations) allow you to define a set of named constants. They're perfect for representing a fixed set of related values like days of the week, status codes, or user roles. Enums make your code more readable, type-safe, and easier to maintain. Let's explore TypeScript enums in depth!

What Are Enums?

An enum is a special TypeScript feature that allows you to define a set of named constants. Instead of using magic strings or numbers throughout your code, you can use descriptive enum members.

Plain Constants vs Enums

JavaScript (No Type Safety)
// JavaScript - Using plain objects or strings
const STATUS_PENDING = "pending";
const STATUS_APPROVED = "approved";
const STATUS_REJECTED = "rejected";

// Easy to make typos
let orderStatus = "pendding";  // Typo!

// No autocomplete
if (orderStatus === "aprroved") {  // Another typo!
  console.log("Order approved");
}

// Magic strings everywhere
function updateStatus(status) {
  // Is "active" a valid status? No idea!
  if (status === "active") {
    // ...
  }
}
TypeScript (Type Safe)
// TypeScript - Using enums
enum OrderStatus {
  Pending = "pending",
  Approved = "approved",
  Rejected = "rejected"
}

// Type-safe, autocomplete works
let orderStatus: OrderStatus = OrderStatus.Pending;

// TypeScript catches typos
if (orderStatus === OrderStatus.Approved) {
  console.log("Order approved");
}

// Clear what values are valid
function updateStatus(status: OrderStatus) {
  if (status === OrderStatus.Pending) {
    // TypeScript knows all possible values
  }
}

Why TypeScript is Better: Enums provide a type-safe way to define named constants. They prevent typos, enable autocomplete, and make code more readable and maintainable.

Key TypeScript Benefits

  • Type safety catches errors before runtime
  • Better IDE autocomplete and IntelliSense
  • Self-documenting code through types
  • Easier refactoring and maintenance
  • Fewer runtime errors in production

Why Use Enums?

  • Type Safety: Prevent invalid values
  • Autocomplete: IDEs suggest valid enum members
  • Readability: Self-documenting code
  • Refactoring: Easy to rename values everywhere
  • No Magic Values: Clear what values are valid

Numeric Enums

Numeric enums are the default in TypeScript. Each member is assigned a numeric value, starting from 0 by default.

Basic Numeric Enums

numeric-enums-basic.ts
// Basic numeric enum (starts at 0)
enum Direction {
  North,    // 0
  South,    // 1
  East,     // 2
  West      // 3
}

// Using the enum
let playerDirection: Direction = Direction.North;

console.log(Direction.North);   // 0
console.log(Direction.South);   // 1
console.log(Direction.East);    // 2
console.log(Direction.West);    // 3

// Type-safe comparisons
if (playerDirection === Direction.North) {
  console.log("Moving north");
}

// Get enum name from value (reverse mapping)
console.log(Direction[0]);  // "North"
console.log(Direction[2]);  // "East"

Custom Starting Values

custom-start.ts
// Start from 1 instead of 0
enum Month {
  January = 1,
  February,    // 2
  March,       // 3
  April,       // 4
  May,         // 5
  June,        // 6
  July,        // 7
  August,      // 8
  September,   // 9
  October,     // 10
  November,    // 11
  December     // 12
}

console.log(Month.January);   // 1
console.log(Month.December);  // 12

let currentMonth: Month = Month.March;
console.log(`Month: ${currentMonth}`);  // 3

Fully Initialized Enums

initialized-enums.ts
// Explicitly set all values
enum HttpStatus {
  OK = 200,
  Created = 201,
  BadRequest = 400,
  Unauthorized = 401,
  Forbidden = 403,
  NotFound = 404,
  InternalServerError = 500
}

// Using in a function
function handleResponse(status: HttpStatus): string {
  switch (status) {
    case HttpStatus.OK:
      return "Success";
    case HttpStatus.Created:
      return "Resource created";
    case HttpStatus.BadRequest:
      return "Invalid request";
    case HttpStatus.NotFound:
      return "Resource not found";
    case HttpStatus.InternalServerError:
      return "Server error";
    default:
      return "Unknown status";
  }
}

console.log(handleResponse(HttpStatus.OK));        // "Success"
console.log(handleResponse(HttpStatus.NotFound));  // "Resource not found"

// Actual values
console.log(HttpStatus.OK);         // 200
console.log(HttpStatus.NotFound);   // 404

💡 Reverse Mapping

Numeric enums have reverse mapping—you can get the enum name from its value: Direction[0] returns "North". This doesn't work with string enums!

String Enums

String enums have string values instead of numbers. They're more readable in logs and debugging.

Basic String Enums

string-enums.ts
// String enum - all members must be initialized
enum OrderStatus {
  Pending = "PENDING",
  Processing = "PROCESSING",
  Shipped = "SHIPPED",
  Delivered = "DELIVERED",
  Cancelled = "CANCELLED"
}

let orderStatus: OrderStatus = OrderStatus.Pending;

console.log(orderStatus);  // "PENDING"

// Great for API responses
function getStatusMessage(status: OrderStatus): string {
  switch (status) {
    case OrderStatus.Pending:
      return "Your order is pending";
    case OrderStatus.Processing:
      return "Your order is being processed";
    case OrderStatus.Shipped:
      return "Your order has been shipped";
    case OrderStatus.Delivered:
      return "Your order has been delivered";
    case OrderStatus.Cancelled:
      return "Your order was cancelled";
  }
}

console.log(getStatusMessage(OrderStatus.Shipped));
// "Your order has been shipped"

String Enums for User Roles

user-roles-enum.ts
// User roles with string enum
enum UserRole {
  Admin = "ADMIN",
  Moderator = "MODERATOR",
  User = "USER",
  Guest = "GUEST"
}

// User type using the enum
type User = {
  id: number;
  name: string;
  role: UserRole;
};

// Check permissions
function canDeletePost(user: User): boolean {
  return user.role === UserRole.Admin || 
         user.role === UserRole.Moderator;
}

function canEditSettings(user: User): boolean {
  return user.role === UserRole.Admin;
}

// Create users
let admin: User = {
  id: 1,
  name: "Yusuf Ibrahim",
  role: UserRole.Admin
};

let regularUser: User = {
  id: 2,
  name: "Amina Hassan",
  role: UserRole.User
};

console.log(`Can ${admin.name} delete posts? ${canDeletePost(admin)}`);
// "Can Yusuf Ibrahim delete posts? true"

console.log(`Can ${regularUser.name} delete posts? ${canDeletePost(regularUser)}`);
// "Can Amina Hassan delete posts? false"

String Enums for API Endpoints

api-endpoints.ts
// API endpoints as string enum
enum ApiEndpoint {
  Users = "/api/users",
  Products = "/api/products",
  Orders = "/api/orders",
  Auth = "/api/auth",
  Profile = "/api/profile"
}

// Function using the enum
async function fetchData(endpoint: ApiEndpoint): Promise<any> {
  console.log(`Fetching from: ${endpoint}`);
  // In real code: const response = await fetch(endpoint);
  return {};
}

// Type-safe API calls
fetchData(ApiEndpoint.Users);
fetchData(ApiEndpoint.Products);

// This would cause an error:
// fetchData("/api/wrong");  // ❌ Error: string not assignable to ApiEndpoint

// Building URLs
function buildApiUrl(endpoint: ApiEndpoint, id?: number): string {
  const baseUrl = "https://api.example.com";
  if (id !== undefined) {
    return `${baseUrl}${endpoint}/${id}`;
  }
  return `${baseUrl}${endpoint}`;
}

console.log(buildApiUrl(ApiEndpoint.Users));      // "https://api.example.com/api/users"
console.log(buildApiUrl(ApiEndpoint.Products, 5)); // "https://api.example.com/api/products/5"

Recommendation: Use string enums for most cases. They're more readable in logs, debugging tools, and API responses. The actual string value is clear without looking up the enum definition.

Heterogeneous Enums

Enums can mix string and numeric values, though this is rarely needed.

heterogeneous-enums.ts
// Mixed string and number enum (not recommended)
enum Mixed {
  No = 0,
  Yes = "YES"
}

console.log(Mixed.No);   // 0
console.log(Mixed.Yes);  // "YES"

// Practical example: Response codes
enum ApiResponse {
  Success = 200,
  Error = "ERROR",
  Unauthorized = 401,
  NotFound = "NOT_FOUND"
}

// This works but is confusing
let response1: ApiResponse = ApiResponse.Success;      // 200
let response2: ApiResponse = ApiResponse.Error;        // "ERROR"
let response3: ApiResponse = ApiResponse.Unauthorized; // 401

Avoid heterogeneous enums unless you have a specific reason. They're confusing and harder to maintain. Stick to either all numbers or all strings.

Const Enums

Const enums are completely removed during compilation, resulting in more optimized code.

const-enums.ts
// Regular enum
enum RegularDirection {
  North,
  South,
  East,
  West
}

// Const enum
const enum ConstDirection {
  North,
  South,
  East,
  West
}

// Using regular enum
let dir1: RegularDirection = RegularDirection.North;

// Using const enum
let dir2: ConstDirection = ConstDirection.North;

// After compilation:
// Regular enum creates an object in JavaScript
// Const enum is replaced with the actual value (0)

console.log(dir1);  // Compiled: console.log(RegularDirection.North);
console.log(dir2);  // Compiled: console.log(0);

When to Use Const Enums

  • Performance-critical code where every byte matters
  • Internal APIs not exposed to external code
  • Build-time constants that won't change

Const Enum Limitations

  • Cannot use reverse mapping (no numeric to string lookup)
  • Cannot iterate over enum members
  • Cannot be used in certain advanced scenarios

⚠️ Const Enum Caution

For most applications, regular enums are better. Only use const enums if you're certain you need the performance optimization and understand the limitations.

Computed and Constant Members

Constant Enum Members

constant-members.ts
// Constant members - evaluated at compile time
enum FileAccess {
  None = 0,
  Read = 1 << 0,      // Bitwise left shift: 1
  Write = 1 << 1,     // Bitwise left shift: 2
  ReadWrite = Read | Write,  // Bitwise OR: 3
  Execute = 1 << 2    // Bitwise left shift: 4
}

console.log(FileAccess.None);      // 0
console.log(FileAccess.Read);      // 1
console.log(FileAccess.Write);     // 2
console.log(FileAccess.ReadWrite); // 3
console.log(FileAccess.Execute);   // 4

// Check permissions
function hasPermission(userAccess: FileAccess, required: FileAccess): boolean {
  return (userAccess & required) === required;
}

let userPermissions: FileAccess = FileAccess.ReadWrite;
console.log(hasPermission(userPermissions, FileAccess.Read));   // true
console.log(hasPermission(userPermissions, FileAccess.Execute)); // false

Computed Enum Members

computed-members.ts
// Computed members - evaluated at runtime
function getValue(): number {
  return 100;
}

enum Mixed {
  A = getValue(),  // Computed
  B,               // Error! Needs initializer after computed member
  C = 200,         // Constant
  D                // 201 (auto-increment from constant)
}

// Better: Keep it simple
enum Simple {
  A = 100,
  B = 200,
  C = 300
}

Enums at Runtime

Unlike type aliases which are erased during compilation, enums create actual JavaScript objects.

runtime-enums.ts
// Enum in TypeScript
enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

// Compiled JavaScript (simplified)
// var Color;
// (function (Color) {
//     Color["Red"] = "RED";
//     Color["Green"] = "GREEN";
//     Color["Blue"] = "BLUE";
// })(Color || (Color = {}));

// You can iterate over enum values
function getAllColors(): string[] {
  return Object.values(Color);
}

console.log(getAllColors());  // ["RED", "GREEN", "BLUE"]

// Get all enum keys
function getAllColorNames(): string[] {
  return Object.keys(Color);
}

console.log(getAllColorNames());  // ["Red", "Green", "Blue"]

// Check if value is valid enum member
function isValidColor(value: string): value is Color {
  return Object.values(Color).includes(value as Color);
}

console.log(isValidColor("RED"));    // true
console.log(isValidColor("YELLOW")); // false

Practical Examples

Example 1: Order Management System

order-system.ts
// Order status enum
enum OrderStatus {
  Pending = "PENDING",
  Confirmed = "CONFIRMED",
  Processing = "PROCESSING",
  Shipped = "SHIPPED",
  Delivered = "DELIVERED",
  Cancelled = "CANCELLED",
  Refunded = "REFUNDED"
}

// Payment method enum
enum PaymentMethod {
  Cash = "CASH",
  Card = "CARD",
  BankTransfer = "BANK_TRANSFER",
  MobileMoney = "MOBILE_MONEY"
}

// Order type
type Order = {
  id: number;
  customerId: number;
  status: OrderStatus;
  paymentMethod: PaymentMethod;
  totalAmount: number;
  createdAt: Date;
};

// Create order
function createOrder(
  customerId: number,
  totalAmount: number,
  paymentMethod: PaymentMethod
): Order {
  return {
    id: Date.now(),
    customerId,
    status: OrderStatus.Pending,
    paymentMethod,
    totalAmount,
    createdAt: new Date()
  };
}

// Update order status
function updateOrderStatus(order: Order, newStatus: OrderStatus): void {
  console.log(`Updating order ${order.id} from ${order.status} to ${newStatus}`);
  order.status = newStatus;
}

// Check if order can be cancelled
function canCancelOrder(order: Order): boolean {
  return order.status === OrderStatus.Pending || 
         order.status === OrderStatus.Confirmed;
}

// Usage
let order = createOrder(101, 50000, PaymentMethod.Card);
console.log(`Order created: ${order.id}`);
console.log(`Status: ${order.status}`);
console.log(`Payment: ${order.paymentMethod}`);

updateOrderStatus(order, OrderStatus.Confirmed);
updateOrderStatus(order, OrderStatus.Processing);

console.log(`Can cancel? ${canCancelOrder(order)}`);  // false

Example 2: User Permission System

permission-system.ts
// User roles
enum UserRole {
  SuperAdmin = "SUPER_ADMIN",
  Admin = "ADMIN",
  Moderator = "MODERATOR",
  Editor = "EDITOR",
  Viewer = "VIEWER",
  Guest = "GUEST"
}

// Permissions
enum Permission {
  CreateUser = "CREATE_USER",
  DeleteUser = "DELETE_USER",
  EditUser = "EDIT_USER",
  ViewUser = "VIEW_USER",
  CreatePost = "CREATE_POST",
  DeletePost = "DELETE_POST",
  EditPost = "EDIT_POST",
  ViewPost = "VIEW_POST"
}

// Role permissions mapping
const rolePermissions: Record<UserRole, Permission[]> = {
  [UserRole.SuperAdmin]: [
    Permission.CreateUser,
    Permission.DeleteUser,
    Permission.EditUser,
    Permission.ViewUser,
    Permission.CreatePost,
    Permission.DeletePost,
    Permission.EditPost,
    Permission.ViewPost
  ],
  [UserRole.Admin]: [
    Permission.CreateUser,
    Permission.EditUser,
    Permission.ViewUser,
    Permission.CreatePost,
    Permission.DeletePost,
    Permission.EditPost,
    Permission.ViewPost
  ],
  [UserRole.Moderator]: [
    Permission.DeletePost,
    Permission.EditPost,
    Permission.ViewPost,
    Permission.ViewUser
  ],
  [UserRole.Editor]: [
    Permission.CreatePost,
    Permission.EditPost,
    Permission.ViewPost
  ],
  [UserRole.Viewer]: [
    Permission.ViewPost,
    Permission.ViewUser
  ],
  [UserRole.Guest]: [
    Permission.ViewPost
  ]
};

// Check if user has permission
function hasPermission(role: UserRole, permission: Permission): boolean {
  return rolePermissions[role].includes(permission);
}

// Usage
let adminRole: UserRole = UserRole.Admin;
let editorRole: UserRole = UserRole.Editor;

console.log(`Admin can delete users? ${hasPermission(adminRole, Permission.DeleteUser)}`);
// false

console.log(`Admin can create posts? ${hasPermission(adminRole, Permission.CreatePost)}`);
// true

console.log(`Editor can delete posts? ${hasPermission(editorRole, Permission.DeletePost)}`);
// false

Example 3: HTTP Request Handler

http-handler.ts
// HTTP methods
enum HttpMethod {
  GET = "GET",
  POST = "POST",
  PUT = "PUT",
  PATCH = "PATCH",
  DELETE = "DELETE"
}

// HTTP status codes
enum HttpStatusCode {
  OK = 200,
  Created = 201,
  NoContent = 204,
  BadRequest = 400,
  Unauthorized = 401,
  Forbidden = 403,
  NotFound = 404,
  InternalServerError = 500
}

// Content types
enum ContentType {
  JSON = "application/json",
  FormData = "application/x-www-form-urlencoded",
  MultipartFormData = "multipart/form-data",
  PlainText = "text/plain"
}

// Request type
type HttpRequest = {
  method: HttpMethod;
  url: string;
  headers: Record<string, string>;
  body?: any;
};

// Response type
type HttpResponse = {
  statusCode: HttpStatusCode;
  contentType: ContentType;
  body: any;
};

// Create request
function createRequest(
  method: HttpMethod,
  url: string,
  body?: any
): HttpRequest {
  return {
    method,
    url,
    headers: {
      "Content-Type": ContentType.JSON
    },
    body
  };
}

// Handle request
function handleRequest(request: HttpRequest): HttpResponse {
  console.log(`${request.method} ${request.url}`);
  
  if (request.method === HttpMethod.GET) {
    return {
      statusCode: HttpStatusCode.OK,
      contentType: ContentType.JSON,
      body: { message: "Data retrieved" }
    };
  }
  
  if (request.method === HttpMethod.POST) {
    return {
      statusCode: HttpStatusCode.Created,
      contentType: ContentType.JSON,
      body: { message: "Resource created" }
    };
  }
  
  return {
    statusCode: HttpStatusCode.BadRequest,
    contentType: ContentType.JSON,
    body: { error: "Invalid method" }
  };
}

// Usage
let getRequest = createRequest(HttpMethod.GET, "/api/users");
let postRequest = createRequest(HttpMethod.POST, "/api/users", { name: "Yusuf" });

let getResponse = handleRequest(getRequest);
let postResponse = handleRequest(postRequest);

console.log(`GET Response: ${getResponse.statusCode} - ${JSON.stringify(getResponse.body)}`);
console.log(`POST Response: ${postResponse.statusCode} - ${JSON.stringify(postResponse.body)}`);

Enums vs Alternatives

Enums vs Union Types

enums-vs-unions.ts
// Using Enum
enum Status {
  Active = "ACTIVE",
  Inactive = "INACTIVE",
  Pending = "PENDING"
}

let status1: Status = Status.Active;

// Using Union Type
type StatusUnion = "ACTIVE" | "INACTIVE" | "PENDING";
let status2: StatusUnion = "ACTIVE";

// Enum advantages:
// - Autocomplete suggests all values
// - Can iterate over values
// - Clear namespace (Status.Active)
// - Runtime object exists

// Union advantages:
// - Simpler, no extra code generated
// - Works directly with strings
// - No compilation overhead

Enums vs Object as Const

enums-vs-objects.ts
// Using Enum
enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

// Using Object as Const
const ColorObj = {
  Red: "RED",
  Green: "GREEN",
  Blue: "BLUE"
} as const;

type ColorType = typeof ColorObj[keyof typeof ColorObj];

// Both work similarly
let enumColor: Color = Color.Red;
let objColor: ColorType = ColorObj.Red;

// Enum: Clearer syntax, built-in TypeScript feature
// Object: More flexible, no extra JavaScript generated

Test Your Knowledge

Type Safety Check

Which enum usage is correct?

enum Direction {
  North,
  South,
  East,
  West
}

// Option A
let direction1: Direction = Direction.North;

// Option B
let direction2: Direction = "North";

// Option C
let direction3: Direction = 0;

// Option D
let direction4 = Direction.East;

Best Practices

  1. Use string enums for most cases—they're more readable
  2. Use PascalCase for enum names (e.g., OrderStatus)
  3. Use PascalCase for enum members (e.g., OrderStatus.Pending)
  4. Avoid heterogeneous enums—stick to all strings or all numbers
  5. Use const enums sparingly—only when you need the optimization
  6. Group related constants into a single enum
  7. Consider union types for simple cases
  8. Document enum purpose with comments for complex enums
enum-best-practices.ts
// ✅ Good: String enum with clear values
enum OrderStatus {
  Pending = "PENDING",
  Processing = "PROCESSING",
  Completed = "COMPLETED",
  Cancelled = "CANCELLED"
}

// ✅ Good: Grouped related constants
enum PaymentMethod {
  Cash = "CASH",
  Card = "CARD",
  BankTransfer = "BANK_TRANSFER",
  MobileMoney = "MOBILE_MONEY"
}

// ❌ Avoid: Heterogeneous enum
enum BadEnum {
  First = 1,
  Second = "SECOND"  // Mixing types
}

// ❌ Avoid: Unclear abbreviations
enum Stat {
  P = "P",
  C = "C",
  A = "A"
}

// ✅ Better: Clear, descriptive names
enum Status {
  Pending = "PENDING",
  Completed = "COMPLETED",
  Active = "ACTIVE"
}

Key Takeaways

  • Enums define a set of named constants for related values
  • Numeric enums auto-increment from 0 (or custom start value)
  • String enums are more readable and better for most use cases
  • Enums provide type safety, autocomplete, and prevent typos
  • Numeric enums have reverse mapping (value → name lookup)
  • Const enums are optimized away during compilation
  • Enums create runtime objects (unlike type aliases)
  • Use enums for status codes, user roles, states, and categories
  • Consider union types as simpler alternative for basic cases
  • Use PascalCase for both enum names and members

What's Next?

Now that you've mastered enums and all the basic types, you're ready to explore Any, Unknown, and Never! In the next lesson, you'll learn about TypeScript's special types—when to use them safely, how they differ from each other, and why they're important for handling edge cases. These advanced types will complete your understanding of TypeScript's type system.

Get ready to handle uncertainty and impossibility with TypeScript's special types!

Mastering TypeScript enums! Check this out!

Previous
Objects and Type Aliases
Next
Any, Unknown, and Never

Never Miss a New TypeScript Tutorial

Join 1,000+ developers learning TypeScript step-by-step. Get new tutorials, type safety tips, and exclusive resources delivered to your inbox - completely FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

TypeScript Tutorials

0 of 30 completed

Your Progress0%

Topics

Getting Started

  • What is TypeScript?
  • TypeScript vs JavaScript
  • Setting Up TypeScript
  • Your First TypeScript Program

Basic Types

  • Primitive Types
  • Arrays and Tuples
  • Objects and Type Aliases
  • Enums
  • Any, Unknown, and Never

Functions & Interfaces

  • Function Types and Signatures
  • Interfaces
  • Optional and Default Parameters
  • Function Overloading

Advanced Types

  • Union and Intersection Types
  • Type Guards and Narrowing
  • Literal Types
  • Type Assertions and Casting

Generics

  • Introduction to Generics
  • Generic Constraints
  • Utility Types

Classes & OOP

  • Classes and Constructors
  • Access Modifiers
  • Inheritance and Polymorphism
  • Abstract Classes and Interfaces

Practical TypeScript

  • Working with Modules
  • TypeScript with React
  • Async/Await and Promises
  • Working with APIs and JSON
  • Type Declarations and DefinitelyTyped
  • TypeScript Best Practices
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo