HackIndia Logo
HackathonsNewsSkillsGrowth
HackIndia LogoContact: +91 9910125804

General

  • Companies
  • Colleges
  • Board of Advisors
  • Brand Ambassadors
  • FAQ
  • Contact
  • Report a Bug

Hackathons

  • Upcoming Hackathons
  • Judges
  • Mentors
  • Partners
  • Participating Colleges
  • Testimonials

Resources

  • About Us
  • Branding
  • Latest News
  • Growth
  • Skills
  • Builders
  • Ecosystem
  • Forum
  • Ideas
  • Prompt Optimizer
  • Games

© 2026 HackIndia. All rights reserved.

Privacy PolicyTerms of ServiceCode of ConductSitemap

Build 2.139 · 05 Nov 2026, 10:27 UTC

    HackIndia
    HackathonsNewsInternshipsSkillsGrowthPro Perks
    ← Ship safer JavaScript with TypeScript

    All the reading

    TypeScript

    8 lessons, about 35 minutes. The check's questions come from these.

    Contents
    Choosing types and setup
    1. 1. Why types save demos
    2. 2. Set up TypeScript cleanly
    Shaping data and functions
    1. 3. Use basic and union types
    2. 4. Model data with aliases and interfaces
    3. 5. Type functions that do work
    4. 6. Use generics without overdoing it
    Reading errors and shipping
    1. 7. Read errors before using any
    2. 8. Submit your typed project repo

    Choosing types and setup

    1. Why types save demos

    4 min

    In 30 seconds
    • Explain why TypeScript catches demo-breaking JavaScript bugs early.
    • Spot the kind of mistakes types can catch before a hackathon submission.
    • Pick a small JavaScript project that is worth converting to TypeScript.

    The demo problem

    JavaScript lets you move fast. It also lets small wrong assumptions reach your demo.

    A value from a form is a string. An API field may be missing. A function may return null when your UI expects text. These bugs often appear only when a judge clicks a path you did not test.

    Key point

    One idea

    TypeScript does not make your app correct. It makes many bad assumptions visible before you run the app.

    Think of it as a build-time check for your JavaScript decisions.

    Example

    Bug before demo

    This JavaScript looks fine until the data shape changes. A college event app might receive this from a local JSON file or a simple backend.

    // JavaScript
    function formatEvent(event) {
      return event.title.toUpperCase() + " at " + event.venue.name;
    }
    
    const eventFromApi = {
      title: "HackIndia Meetup",
      venue: null
    };
    
    console.log(formatEvent(eventFromApi));
    // Runtime crash: Cannot read properties of null
    Example

    Type catches it

    With TypeScript, you describe what the function needs. If venue can be null, the code must handle it before the build or type-check passes.

    type Venue = {
      name: string;
    };
    
    type Event = {
      title: string;
      venue: Venue | null;
    };
    
    function formatEvent(event: Event) {
      return event.title.toUpperCase() + " at " + event.venue.name;
      // TypeScript warns: event.venue is possibly null
    }

    What types help with

    2. Set up TypeScript cleanly

    4 min

    In 30 seconds
    • Install TypeScript in a JavaScript project without changing everything at once.
    • Create a clean tsconfig.json for a small app you can build in public.
    • Add npm scripts so recruiters can see type-check and build results.
    Key point

    One clean rule

    Set up TypeScript as a project tool, not a global shortcut. Keep it in devDependencies, commit the config, and run it through npm scripts.

    This makes your repo work on your laptop, your teammate’s laptop, and a recruiter’s machine.

    What setup means

    TypeScript needs two things: the TypeScript package and a tsconfig.json file. The package gives you the compiler. The config tells it what files to read and how strict to be.

    In this lesson, you will not convert every file yet. You will prepare the project so later lessons can add types safely.

    Your to-do

    Install TypeScript

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    Shaping data and functions

    3. Use basic and union types

    4 min

    In 30 seconds
    • Add basic TypeScript types to variables you control.
    • Use union types when a value has a small set of valid options.
    • Avoid any by narrowing values before using them.
    Key point

    The core idea

    A type is a promise about what a value can be. A union type is a promise with choices, like "pending" or "paid".

    Use basic types for simple values. Use unions when only a few values are valid.

    Basic types you use

    You will use string, number, boolean, null, undefined, array types, and object shapes often. Lesson 4 will go deeper on object modelling, so keep this lesson focused on small values.

    Do not type everything by hand. TypeScript can infer many values. Add types where they make intent clear, especially data coming from forms, APIs, or config.

    Example

    Simple typed values

    This is the kind of code you might have in a hackathon app that tracks orders, events, or project tasks.

    Reading errors and shipping

    7. Read errors before using any

    4 min

    In 30 seconds
    • Read a TypeScript error from the bottom line up.
    • Fix the real mismatch instead of hiding it with any.
    • Use unknown and narrowing when data shape is not trusted.
    Key point

    One rule

    Do not reach for any when TypeScript complains. Read the error, find what TypeScript expected, then fix the data, the type, or the check.

    any turns off the useful part of TypeScript. It can make your demo build while leaving the crash inside.

    How errors speak

    Most TypeScript errors have two sides. One side says what value you gave. The other says what type was expected.

    Start with the last line of the error. Then move up only if you need the file path or the exact call site.

    Example

    Read this error

    This app stores hackathon expenses. The function wants a number. The UI is passing a string from an input field.

    type Expense = {
      title: string;
      amount: number;
    };
    
    function addExpense(expense: Expense) {
      console.log(`${expense.title}: ₹${expense.amount}`);
    }
    
    const amountFromInput = "499";
    
    addExpense({
      title: "Domain name",
      amount: amountFromInput,
    });
    
    // TypeScript error:
    // Type 'string' is not assignable to type 'number'.

    10 questions, 7 to pass.

    Sign in to take the test

    Types are useful when your app has moving parts: forms, API responses, user roles, payments, project cards, filters, routes, and database records.

    For a hackathon repo, typed code also shows reviewers that you thought about data, not only screens.

    Common mistake

    Common wrong belief

    Beginners think TypeScript is only for large company codebases. It is also useful for a 2-day hackathon app.

    The smaller the team, the more you need simple checks. You may be coding at 2 am, tired, after classes or labs. Types catch boring mistakes when your brain does not.

    Tip

    Use AI carefully

    You can ask ChatGPT, Gemini, or Claude to convert a small file to TypeScript. Do not paste it blindly.

    Check that the AI did not hide errors with any, remove useful null checks, or invent fields that your real data does not have.

    Prompt you can use:
    Convert this JavaScript file to TypeScript.
    Keep the same behaviour.
    Add types for function inputs and returned values.
    Do not use any unless there is no better safe type.
    Explain every type you add in 5 short bullets.
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    0 of 5 done

    npm init -y
    npm install --save-dev typescript
    npx tsc --version
    Example

    Small tsconfig

    Create tsconfig.json at the project root. This is a safe starting point for a small app.

    It checks your source files, writes build output to dist, and avoids checking installed packages.

    {
      "compilerOptions": {
        "target": "ES2020",
        "module": "ES2020",
        "moduleResolution": "Bundler",
        "rootDir": "src",
        "outDir": "dist",
        "strict": true,
        "noEmitOnError": true,
        "skipLibCheck": true
      },
      "include": ["src"]
    }
    Tip

    Start with src

    Put your app code inside a src folder. Keep generated files in dist. This gives your repo a clean shape that is easy to inspect.

    If your app already has files in the root, move one small file into src first. Do not reorganise everything five minutes before a hackathon demo.

    Example

    Add scripts

    Your README should later show the same commands you use locally. Add scripts now so type-checking is one command.

    For a basic TypeScript project, typecheck checks only. build checks and writes JavaScript into dist.

    {
      "scripts": {
        "typecheck": "tsc --noEmit",
        "build": "tsc"
      },
      "devDependencies": {
        "typescript": "^5.0.0"
      }
    }
    Common mistake

    Avoid global installs

    Do not depend on npm install -g typescript for your project. It may work on your laptop and fail for someone else.

    Use npm install --save-dev typescript and run npx tsc or npm run typecheck. That proves the repo carries its own setup.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    npm run typecheck
    npm run build
    let teamName: string = "Code Mandali";
    let membersCount: number = 4;
    let isSubmitted: boolean = false;
    
    let tags: string[] = ["typescript", "hackathon", "frontend"];
    let scores: number[] = [8, 9, 7];
    
    let selectedCoupon: string | null = null;
    selectedCoupon = "HACK50";

    When to use unions

    Use a union type when a value can be one of a few known types or labels. This catches spelling mistakes and invalid states before your demo.

    A union is made with the pipe symbol. Read string | null as "string or null".

    Example

    Union for status

    Instead of saving any random string as a payment status, list the only allowed values. This fits Indian app flows like UPI payment, event registration, or food ordering.

    let paymentStatus: "pending" | "paid" | "failed" = "pending";
    
    paymentStatus = "paid";
    // paymentStatus = "done"; // TypeScript error
    
    function statusLabel(status: "pending" | "paid" | "failed") {
      if (status === "paid") {
        return "Payment received";
      }
    
      if (status === "failed") {
        return "Payment failed";
      }
    
      return "Waiting for payment";
    }
    Common mistake

    Do not reach for any

    any turns off checking for that value. It is useful only as a short temporary step when converting old JavaScript.

    If you use any for form data, API data, or user input, TypeScript cannot help you catch wrong assumptions.

    // Weak
    let amount: any = "499";
    console.log(amount.toFixed(2)); // Breaks at runtime
    
    // Safer
    let amountText: string = "499";
    let amountInRupees: number = Number(amountText);
    console.log(amountInRupees.toFixed(2));
    Tip

    Narrow before use

    When a value has a union type, check what it is before using methods that only work on one type. This is called narrowing.

    AI tools often write code that assumes a value exists. Check for null and undefined in AI-generated code before you copy it.

    let phoneNumber: string | undefined = undefined;
    
    if (phoneNumber) {
      console.log(phoneNumber.toUpperCase());
    } else {
      console.log("No phone number added yet");
    }
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    4. Model data with aliases and interfaces

    4 min

    In 30 seconds
    • Create type aliases for app data shapes.
    • Use interfaces when objects should be extended later.
    • Model API, form, and UI data before writing logic.
    Key point

    One idea

    Give every important object in your app a name. A named data shape is easier to reuse, review, and fix than random inline object types.

    Why this matters

    Most hackathon bugs come from wrong assumptions about data. A user may not have a profile photo. A payment status may be pending. A college event may not have a venue yet.

    Aliases and interfaces let you write these rules once. Then TypeScript checks every place that uses the data.

    Example

    Use a type alias

    A type alias is good for naming one shape or a union. Use it for API data, form data, IDs, and status values.

    type ProjectStatus = "draft" | "submitted" | "reviewed";
    
    type TeamMember = {
      id: string;
      name: string;
      college: string;
      role: "frontend" | "backend" | "design" | "other";
      githubUrl?: string;
    };
    
    type HackathonProject = {
      id: string;
      title: string;
      status: ProjectStatus;
      members: TeamMember[];
      repoUrl: string;
    };
    Example

    Use an interface

    An interface is also for object shapes. It is useful when you expect the shape to grow, or when different files add related fields.

    interface UserProfile {
      id: string;
      name: string;
      email: string;
    }
    
    interface StudentProfile extends UserProfile {
      college: string;
      graduationYear: number;
    }
    
    const student: StudentProfile = {
      id: "u_101",
      name: "Asha",
      email: "[email protected]",
      college: "VIT Chennai",
      graduationYear: 2026,
    };
    Your to-do

    Choose one

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 4 done

    Common mistake

    Avoid loose objects

    Do not pass big objects around without a named type. You will forget fields or spell them differently in another file.

    Also avoid making every field optional with ?. Optional means the value can be missing. Use it only when your UI can handle that case.

    // Weak: hard to reuse and easy to copy badly
    function showMember(member: { name: string; role: string; githubUrl?: string }) {
      return member.name;
    }
    
    // Better: one named shape used everywhere
    function showMember(member: TeamMember) {
      return member.name;
    }
    Tip

    Ask AI carefully

    You can ask ChatGPT, Gemini, or Claude to suggest types from sample JSON. Paste a small API response or form object and ask for TypeScript types.

    Check the output. Look for fields that should be optional, string values that should be unions, and numbers that were guessed wrongly.

    Prompt:
    Convert this sample project JSON into TypeScript types.
    Use unions for status fields.
    Mark fields optional only if they can be missing.
    
    {
      "id": "p_1",
      "title": "UPI Splitter",
      "status": "submitted",
      "repoUrl": "https://github.com/name/upi-splitter"
    }
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    5. Type functions that do work

    5 min

    In 30 seconds
    • Add types to function parameters and return values without slowing down.
    • Use optional and default parameters safely in real app code.
    • Catch wrong inputs before your project reaches the demo table.
    Key point

    Main idea

    A function is a contract. Type the inputs it accepts and the output it promises.

    In a hackathon project, most bugs hide in small helper functions: price totals, filters, form validation, API formatting. Function types make those bugs visible early.

    Where to type

    Type parameters first. Then type the return value when the function is shared, exported, or important to your app flow.

    TypeScript can infer many return types. But for functions used by UI, API calls, or payments, writing the return type makes your intent clear to teammates and recruiters reading your repo.

    Example

    Basic function types

    Here is a small college-event helper. It calculates the payable amount after a student discount.

    The return type is number. If someone returns a string like "₹120", TypeScript will complain before the build passes.

    type TicketType = "student" | "regular";
    
    function calculateTicketPrice(basePrice: number, ticketType: TicketType): number {
      if (ticketType === "student") {
        return basePrice * 0.7;
      }
    
      return basePrice;
    }
    
    const amountToPay = calculateTicketPrice(200, "student");
    Your to-do

    Type real work

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Objects in functions

    Most useful functions take objects. Use the aliases and interfaces you learned earlier instead of repeating shapes everywhere.

    This makes the function readable and keeps your app data consistent.

    interface Expense {
      title: string;
      amount: number;
      paidBy: string;
    }
    
    function formatExpense(expense: Expense): string {
      return `${expense.title}: ₹${expense.amount} paid by ${expense.paidBy}`;
    }
    
    const chaiExpense: Expense = {
      title: "Team chai",
      amount: 120,
      paidBy: "Asha"
    };
    
    console.log(formatExpense(chaiExpense));
    Tip

    Optional vs default

    Use an optional parameter when the value may be missing. Use a default parameter when you want a fallback.

    Default parameters are cleaner for common UI helpers, because the function always has a usable value inside.

    function createGreeting(name: string, college = "your college"): string {
      return `Hi ${name} from ${college}`;
    }
    
    createGreeting("Ravi");
    createGreeting("Ravi", "VIT");
    
    function sendInvite(email: string, phone?: string): string {
      if (phone) {
        return `Invite sent to ${email} and ${phone}`;
      }
    
      return `Invite sent to ${email}`;
    }
    Common mistake

    Do not hide errors

    Do not use any for function parameters just to remove red lines. That turns TypeScript back into JavaScript at the exact place where bugs enter.

    If you are unsure, ask AI to suggest a type from sample data. Then check the result yourself: are numbers really numbers, can values be missing, and are there only fixed options?

    // Weak: accepts anything
    function saveUser(user: any) {
      return user.email.toLowerCase();
    }
    
    // Better
    type User = {
      name: string;
      email: string;
    };
    
    function saveUser(user: User): string {
      return user.email.toLowerCase();
    }
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    6. Use generics without overdoing it

    5 min

    In 30 seconds
    • Use generics when a type must be remembered from input to output.
    • Write small reusable helpers without losing the exact data type.
    • Avoid generic code when a simple type is clearer.
    Key point

    The core idea

    Use a generic when your function, type, or component must work with many types and keep the exact type linked across the code.

    If the type does not need to travel from input to output, you probably do not need a generic.

    Why it matters

    In hackathon apps, you often repeat the same pattern: load users, load events, filter tasks, pick one item, store API responses. Generics let you write one helper and still keep strong types.

    This helps your repo look cleaner to reviewers. It also avoids switching back to any just because one helper is shared across different data.

    Example

    Simple reusable helper

    Here is a helper that returns the first item from any list. The generic T means TypeScript remembers what the list contains.

    function first<T>(items: T[]): T | undefined {
      return items[0];
    }
    
    type Student = {
      id: string;
      name: string;
      college: string;
    };
    
    const names = ["Asha", "Ravi", "Meera"];
    const firstName = first(names);
    // firstName is string | undefined
    
    const students: Student[] = [
      { id: "s1", name: "Asha", college: "VIT" }
    ];
    const firstStudent = first(students);
    // firstStudent is Student | undefined
    Your to-do

    How to use one

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Typed API shape

    A common use is wrapping API results. The outer shape is the same, but the data changes for each call.

    type ApiResult<T> = {
      ok: boolean;
      data: T;
      error?: string;
    };
    
    type Event = {
      id: string;
      title: string;
      feeRupees: number;
    };
    
    const eventResult: ApiResult<Event[]> = {
      ok: true,
      data: [
        { id: "e1", title: "College Hack Night", feeRupees: 0 }
      ]
    };
    
    const title = eventResult.data[0]?.title;
    // TypeScript knows title is string | undefined
    Common mistake

    Do not overdo it

    Beginners often add generics to look advanced. This makes code harder to read and does not catch more bugs.

    If a function only accepts strings, write string. If a type is used once and has no changing inner data, keep it simple.

    // Too much
    function shout<T extends string>(text: T): string {
      return text.toUpperCase();
    }
    
    // Clearer
    function shout(text: string): string {
      return text.toUpperCase();
    }
    Tip

    Ask AI carefully

    You can ask an AI tool to suggest where generics help in your project. Do not accept a rewrite blindly.

    Check that each generic connects at least two places, like input to output or wrapper to data. If it appears only once, it is usually not useful.

    Prompt:
    I am converting this JavaScript file to TypeScript.
    Suggest only the places where a generic would make the types safer.
    Do not add generics for simple string or number functions.
    Explain why each generic is needed.
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Your to-do

    Fix the mismatch

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 4 done

    const rawAmount = "499";
    const amount = Number(rawAmount);
    
    if (Number.isNaN(amount)) {
      throw new Error("Enter a valid amount");
    }
    
    addExpense({
      title: "Domain name",
      amount,
    });
    Common mistake

    The any shortcut

    This silences the error, but it also removes protection. Now amount could be a string, object, or undefined, and TypeScript will not warn you.

    Use any only when you have a clear reason and a comment explaining it. In a hackathon repo, avoid it in normal app code.

    const amountFromInput: any = "499";
    
    addExpense({
      title: "Domain name",
      amount: amountFromInput,
    });
    Tip

    Use unknown first

    When data comes from localStorage, fetch, a form, or an AI-generated mock file, you may not trust its shape. Use unknown, then check it before using it.

    This keeps TypeScript strict without pretending you know the data.

    function parseExpense(data: unknown): Expense {
      if (
        typeof data === "object" &&
        data !== null &&
        "title" in data &&
        "amount" in data &&
        typeof data.title === "string" &&
        typeof data.amount === "number"
      ) {
        return {
          title: data.title,
          amount: data.amount,
        };
      }
    
      throw new Error("Invalid expense data");
    }
    Tip

    Use AI carefully

    You can paste a TypeScript error into ChatGPT, Gemini, or Claude and ask: “Explain this error and suggest a type-safe fix without using any.”

    Check the answer. It should keep useful types, add checks near untrusted data, and not hide the problem with type assertions like as any.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    8. Submit your typed project repo

    5 min

    In 30 seconds
    • Prepare a TypeScript repo that a reviewer can run without asking you.
    • Add proof that your project builds or type-checks successfully.
    • Submit a clean HackIndia project link with typed code, README, and evidence.
    Key point

    Proof beats claims

    A TypeScript project is not proven by saying “built with TypeScript”. It is proven when a reviewer can open your repo, install it, run one command, and see the type-check or build pass.

    Your goal is simple: make your repo easy to inspect in five minutes.

    Your to-do

    What your repo needs

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Useful package scripts

    Your scripts should match your project. A plain TypeScript app may use tsc. A Vite app may use vite and tsc. Do not copy commands that fail in your repo.

    Before submission, run the same command you put in the README.

    {
      "scripts": {
        "dev": "vite",
        "typecheck": "tsc --noEmit",
        "build": "tsc && vite build"
      }
    }
    Example

    README setup section

    A recruiter or judge may be checking your repo late at night after many submissions. Help them run it without DMing you.

    Mention Node.js if your app needs it. Keep environment variable names clear, but never commit real secrets.

    # Campus Expense Splitter
    
    A small TypeScript app to split group expenses for college trips and hostel orders.
    
    ## Tech stack
    - TypeScript
    - Vite
    - React
    
    ## Setup
    1. Clone the repo
    2. Run npm install
    3. Run npm run typecheck
    4. Run npm run dev
    
    ## Build proof
    Last checked locally:
    npm run typecheck
    Result: passed
    
    ## Notes
    Create a .env file from .env.example if you use API keys.
    Tip

    Use AI carefully

    You can ask ChatGPT, Gemini, or Claude to review your README before submission. Paste your README and package.json, then ask: “Can a first-time reviewer run this TypeScript project from these steps?”

    Check the answer yourself. AI may suggest commands for tools you do not use. Only keep commands you have tested in your own terminal.

    Common mistake

    Common submission mistake

    Many builders submit a repo that works only on their laptop. Missing scripts, missing env examples, or a README with old commands can make a good project look broken.

    Another mistake is hiding TypeScript errors with any just before submission. Lesson 7 already covered this. For your final repo, prefer a smaller working feature over a larger unsafe one.

    Your to-do

    Final repo check

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done