Part 0.3 — Modern JavaScript & TypeScript Essentials
Every full-stack engineer needs to speak two dialects of the same language: modern JavaScript for flexibility and TypeScript for precision. Together, they form the communication layer between your ideas and the browser, your APIs, and your database.
Let’s understand how these languages evolved — and how to write clean, type-safe code that scales.
1. From JavaScript to TypeScript — Why It Matters
JavaScript (ES6+) is the web’s lingua franca. TypeScript builds upon it with static typing, interfaces, and tooling that prevent runtime bugs before they happen.
You’ll use TypeScript everywhere:
In React, to define component props and custom hooks
In NestJS, to structure controllers, DTOs, and services
In Prisma, to ensure your database schema aligns with your code
By mastering it now, you’ll avoid silent failures later.
2. Essential Modern JavaScript (ES6+) Features
Before layering on TypeScript, make sure you’re fluent in these ES6+ features — they’re foundational in both React and NestJS codebases.
Destructuring & Spread:
const user = { id: 1, name: "Ava", role: "admin" };
const { name, ...details } = user;
console.log(name); // AvaArrow Functions:
const add = (a: number, b: number) => a + b;Template Literals:
const greet = (name: string) => `Hello, ${name}!`;Modules (import/export):
export const API_URL = "http://localhost:3000";
import { API_URL } from "./config";Async/Await:
async function fetchUsers() {
const res = await fetch("/api/users");
return res.json();
}Promises and async/await form the backbone of every network request between your React frontend and NestJS backend.
3. TypeScript Fundamentals
TypeScript extends JavaScript with static type checking. Think of it as guardrails that prevent logical errors while you’re coding.
Basic Types:
let isActive: boolean = true;
let score: number = 95;
let username: string = "Ava";Arrays and Tuples:
const tags: string[] = ["nestjs", "prisma", "typescript"];
const pair: [string, number] = ["count", 5];Interfaces and Types:
interface User {
id: number;
name: string;
email?: string; // optional
}
type Role = "admin" | "editor" | "viewer";Functions:
function greetUser(user: User): string {
return `Hello, ${user.name}`;
}Generics:
function identity<T>(value: T): T {
return value;
}These generics are crucial when you build reusable utilities in React hooks or backend repositories.
4. Working with Type Inference
TypeScript’s compiler infers most types automatically:
const counter = 10; // inferred as numberAvoid over-declaring — let inference work where possible. But for APIs, DTOs, and database contracts, always be explicit. That’s where correctness matters most.
5. Real-World Example: Fetching Data with Types
Let’s combine everything into a small full-stack scenario.
Imagine fetching users from a NestJS REST API.
Frontend (React + TypeScript):
// src/hooks/useUsers.ts
export interface User {
id: number;
name: string;
email: string;
}
export async function fetchUsers(): Promise<User[]> {
const res = await fetch("/api/users");
if (!res.ok) throw new Error("Failed to fetch users");
return res.json();
}Backend (NestJS Controller + Service):
// src/users/users.controller.ts
@Get()
async getUsers(): Promise<User[]> {
return this.usersService.findAll();
}
// src/users/users.service.ts
async findAll(): Promise<User[]> {
return this.prisma.user.findMany();
}Database (Prisma Schema):
model User {
id Int @id @default(autoincrement())
name String
email String @unique
}Every layer shares the same User shape — enforced by TypeScript and Prisma.
No more guessing field names or types across the stack.
6. Validation and Safety
Even with TypeScript, you need runtime validation.
In NestJS, use class-validator; in React, tools like Zod or Yup.
Example:
import { IsEmail, IsString } from 'class-validator';
export class CreateUserDto {
@IsString()
name: string;
@IsEmail()
email: string;
}If an invalid payload reaches your backend, it fails safely — before corrupting data.
7. TypeScript in the Build Pipeline
Your toolchain (pnpm + TypeScript) keeps your stack consistent.
Initialize your project with:
pnpm add -D typescript ts-node @types/node
pnpm tsc --initIn a monorepo setup (which we’ll use later), shared interfaces can live in /packages/types — ensuring React and NestJS always agree on API contracts.
8. Productivity Tips
Use
strictmode intsconfig.json— it catches subtle bugs early.Use
eslint+@typescript-eslintfor consistency.Avoid
anylike a virus; useunknownor proper unions instead.Leverage VS Code’s “Go to Definition” — your best debugging ally.
9. Closing Thoughts
JavaScript gives you creativity; TypeScript gives you control.
When combined, they make your code predictable, maintainable, and production-grade.
Next up, we’ll move from language syntax to structure — in Part 0.4, you’ll learn how HTML and CSS build the visual foundation before React takes over.
Comments