TypeScriptYour First Program

Your First TypeScript Program

TypeScript is JavaScript with a type layer on top. Before your code runs in the browser or Node.js, the TypeScript compiler (tsc) reads your .ts files, checks that all the types are consistent, and emits plain .js files. This page walks you through that entire cycle — create, compile, inspect, run — step by step.

Prerequisites

You need Node.js and npm installed. TypeScript is installed as a development dependency or globally via npm.

  1. Node.js 18 or later (https://nodejs.org)

  2. npm (bundled with Node.js)

  3. A terminal / command prompt

  4. A text editor (VS Code works great — it has TypeScript support built in)

Step 1 — Install TypeScript

Create a new folder for this project, then install TypeScript locally:

Bash
mkdir hello-ts
cd hello-ts
npm init -y
npm install --save-dev typescript

After installation, the TypeScript compiler lives at node_modules/.bin/tsc. You can run it directly, or use npx tsc to have npm find it for you.

Bash
npx tsc --version
Version 5.5.4
Tip
Install TypeScript locally per-project rather than globally. This way every project pins its own version, and your CI server uses the same version as your laptop.
Step 2 — Create hello.ts

Create a file called hello.ts in your project folder and add this code:

TS
// hello.ts

function greet(name: string): string {
  return `Hello, ${name}! Welcome to TypeScript.`;
}

const message: string = greet('World');
console.log(message);

Take a moment to notice the type annotations:

  • name: string — the parameter name must be a string
  • : string after the parentheses — the function must return a string
  • const message: string — the variable holds a string

These annotations do not change what the code does at runtime. They are instructions to the TypeScript compiler about what types are expected. If you violate them, tsc will refuse to compile.

Step 3 — Compile with tsc

Run the compiler, pointing it at your source file:

Bash
npx tsc hello.ts

If everything is correct, the compiler exits silently and creates hello.js in the same folder. No output means success — that is the Unix convention.

Note
If you see a list of errors, the compiler found a type problem. Read the error message — it tells you the file, line number, and what went wrong.
Step 4 — Inspect the Generated .js

Open hello.js. Here is what TypeScript emitted:

JS
// hello.js  (generated by tsc)

function greet(name) {
  return `Hello, ${name}! Welcome to TypeScript.`;
}

var message = greet('World');
console.log(message);

Notice what changed and what did not:

  • Type annotations are gone. name: string became just name. JavaScript engines do not understand TypeScript syntax, so tsc strips all the types before emitting.
  • The template literal survived. TypeScript targets ES3 by default for maximum compatibility. In newer targets (--target ES2015 or later) template literals are kept as-is.
  • const became var when targeting ES3/ES5. Use --target ES2020 to keep const and let.
Tip
The generated JavaScript is what actually runs. TypeScript is purely a compile-time tool — once you have the .js file, TypeScript is out of the picture.
Step 5 — Run with Node

Execute the compiled file with Node.js:

Bash
node hello.js
Hello, World! Welcome to TypeScript.

The compile-run cycle in full:

Bash
npx tsc hello.ts && node hello.js
The Compile-Run Mental Model

Understanding this two-step model is the key insight for new TypeScript developers:

  1. You write .ts source files with type annotations

  2. tsc reads the .ts files, checks types, and emits .js files

  3. Node.js (or the browser) executes the .js files — it never sees the .ts

  4. Type errors stop compilation; runtime errors happen later when the .js runs

This means TypeScript catches an entire class of bugs before you ever run the program. But it cannot catch every bug — only type-level mistakes. Logic errors still show up at runtime.

Introducing a Deliberate Type Error

Let's break the code on purpose to see what the compiler does. Change the greet call to pass a number instead of a string:

TS
// hello.ts  — broken version

function greet(name: string): string {
  return `Hello, ${name}! Welcome to TypeScript.`;
}

const message: string = greet(42);  // ← pass a number
console.log(message);

Bash
npx tsc hello.ts
hello.ts:7:30 - error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.

7 const message: string = greet(42);  // ← pass a number
                                ~~

Found 1 error in hello.ts:7

Read this error from top to bottom:

  • hello.ts:7:30 — the error is in hello.ts, line 7, column 30
  • TS2345 — the TypeScript error code (useful for searching the docs)
  • Argument of type 'number' is not assignable to parameter of type 'string' — plain English description of the problem
  • The squiggly underline points exactly at 42
Success
The compiler caught the bug before the code ever ran. In JavaScript you would only find this at runtime — or worse, not at all, because JavaScript silently coerces 42 to "42" in many contexts.
Wrong Return Type

Here is another type error — returning the wrong type from a function:

TS
function greet(name: string): string {
  return 42;  // ← number, but function is declared to return string
}
hello.ts:2:10 - error TS2322: Type 'number' is not assignable to type 'string'.

2   return 42;
           ~~
Type Annotations on Variables

You can annotate variables directly, though TypeScript can usually infer the type from the initial value:

TS
// Explicit annotation
const name: string = 'Alice';
const age: number = 30;
const active: boolean = true;

// Inferred — same result, less typing
const name2 = 'Alice';   // TypeScript infers: string
const age2 = 30;         // TypeScript infers: number
const active2 = true;    // TypeScript infers: boolean

// Annotation required when the type can't be inferred
let score: number;       // no initial value → must annotate
score = 100;
Tip
Prefer letting TypeScript infer types when the value makes the type obvious. Add explicit annotations when the variable is declared without an initial value, or when you want to be intentionally clear for readers of the code.
String Interpolation in TypeScript

TypeScript supports the same template literals as modern JavaScript. The types make them more useful because the compiler knows what you are interpolating:

TS
function formatUser(name: string, age: number): string {
  return `${name} is ${age} years old.`;
}

console.log(formatUser('Alice', 30));
// → Alice is 30 years old.

// The compiler knows age is a number, so this is fine:
console.log(`Next year: ${age + 1}`);  // TS knows age is number

// But this would be a type error if age were typed as string:
// const badAge: string = '30';
// console.log(badAge + 1);  // string + number = "301" in JS — not what you want
hello.ts vs hello.js — Side by Side

Here is the same greeting program shown side by side as TypeScript source and the emitted JavaScript (targeting ES2020):

TS
// hello.ts (TypeScript source)

function greet(name: string, times: number = 1): string {
  const lines: string[] = [];
  for (let i: number = 0; i < times; i++) {
    lines.push(`[${i + 1}] Hello, ${name}!`);
  }
  return lines.join('\n');
}

const output: string = greet('World', 3);
console.log(output);

JS
// hello.js (emitted by tsc --target ES2020)

function greet(name, times = 1) {
  const lines = [];
  for (let i = 0; i < times; i++) {
    lines.push(`[${i + 1}] Hello, ${name}!`);
  }
  return lines.join('\n');
}

const output = greet('World', 3);
console.log(output);
[1] Hello, World!
[2] Hello, World!
[3] Hello, World!

The emitted JavaScript is clean, readable, and equivalent to what you would write by hand. TypeScript adds zero runtime overhead — the type annotations simply disappear.

Workflow Summary
  1. Write your logic in .ts files with type annotations

  2. Run npx tsc to compile — fix any errors it reports

  3. Run the emitted .js files with node or deploy them to a browser

  4. During development, use tsc --watch to recompile on every save

Bash
# One-time compile
npx tsc hello.ts

# Watch mode — recompiles whenever the file changes
npx tsc hello.ts --watch
Warning
Always compile from .ts source — never hand-edit the generated.js files. Your changes will be overwritten the next timetsc runs.
Quick Reference
  • hello.ts → source file you edit

  • npx tsc hello.ts → compiles to hello.js

  • node hello.js → executes the compiled output

  • Type annotations use the colon syntax: name: string

  • Return type goes after the closing parenthesis: ): string

  • Type errors block compilation — fix them before running

  • tsc --watch recompiles automatically on save

Success
You have written, compiled, and run your first TypeScript program — and watched the compiler catch a type error before the code ever ran. That is the core TypeScript workflow. Everything else builds on this foundation.