TypeScript: Your First TypeScript Program
Last updated: 2026-08-26
Now that you've finished learning about installation and configuration, it's time to write your first TypeScript program—walk through the entire TypeScript workflow, from writing the code to running it.
1. Create a project file
In the project directory created in the previous lesson, create a new folder named src/hello.ts:
my-project/
├── src/
│ └── hello.ts ← Create this file
├── tsconfig.json
└── package.json
Enter the following code in hello.ts:
// First TypeScript Program
let username: string = "Charlie";
let age: number = 18;
function greet(name: string, userAge: number): string {
return name + " This year " + userAge + " years old";
}
console.log(greet(username, age));
The biggest difference between this code and JavaScript is that each variable and parameter is followed by a type annotation (: string, : number).
2. A First Look at Type Annotations
Type annotations are the core syntax of TypeScript, and their format is very simple: variable name + colon + type.
let Variable Name: Type = value;
(1) Common Annotations for Basic Types
let name: string = "Diana"; // String
let age: number = 20; // Numbers
let isStudent: boolean = true; // Boolean value
let score: number = 95.5; // Decimals are also number
let nothing: null = null; // null
let empty: undefined = undefined; // undefined
(2) Function Type Annotations
Functions must specify two parts: parameter types and return types.
function Function Name(Parameters: Parameter Types): Return Type {
// Function Body
}
- Parameter type: Add
: typeafter each parameter - Return type: Add
: typeafter the parentheses containing the parameters
▶ Example: Functions with type annotations
Output:
8
Hello The World
void:function log(msg: string): void { console.log(msg); }
3. Compiling TypeScript Code
After writing the .ts file, you need to compile it into .js before you can run it.
(1) Manually Compiling a Single File
tsc src/hello.ts
This will create a file named src/hello.js in the same directory. Open it, and you'll see that all the type annotations have disappeared:
// Compiled hello.js
var username = "Charlie";
var age = 18;
function greet(name, userAge) {
return name + " This year " + userAge + " years old";
}
console.log(greet(username, age));
This is TypeScript’s type erasure—type annotations only take effect at compile time, and the resulting JavaScript code is almost identical to hand-written JS.
(2) Compile the entire project using tsconfig.json
If your project contains tsconfig.json, simply run the following command in the project's root directory:
tsc
The compiler will batch-compile all .ts files according to the rootDir and outDir entries in the configuration file.
▶ Example: Compile and Run
# Go to the project directory
cd my-project
# Compilation(According to tsconfig.json Layout)
tsc
# Run the compiled JS
node dist/hello.js
Output:
Charlie This year 18 years old
dist/hello.js, not src/hello.ts. The TypeScript development workflow is always: write .ts → compile → run .js.
4. Experience the Power of Type Checking
The core value of TypeScript—detecting errors at compile time. Let’s intentionally write some incorrect code and see how TypeScript catches you.
(1) Type mismatch
let score: number = 90;
score = "Excellent"; // ❌ Error:You cannot convert the type"string"Assigned to Type"number"
This code runs "legally" in JavaScript, but problems arise when score is used in mathematical operations later on. TypeScript catches this directly at compile time.
(2) Invalid parameter type
function add(a: number, b: number): number {
return a + b;
}
add(3, "5"); // ❌ Error:Type"string"Parameters cannot be assigned to types"number"parameters
In JavaScript, add(3, "5") returns "35" (string concatenation), which is almost certainly not the result you want. TypeScript alerts you in advance that you’ve passed the wrong argument.
(3) Calling a method that does not exist
let name: string = "Charlie";
name.toFixed(2); // ❌ Error:Type"string"The property does not exist"toFixed"
toFixed is a method of type number, but it does not exist on string. JavaScript would throw a TypeError error at runtime, but TypeScript catches it at compile time.
▶ Example: Comparing Error Detection in JavaScript and TypeScript
// ===== JavaScript Version:The problem wasn't discovered until runtime =====
let userAge = "25"; // String "25"
let nextYear = userAge + 1; // No errors will occur,But the result was "251" rather than 26
console.log(nextYear); // Output "251" —— That's not what we want.!
// ===== TypeScript Version:Intercepted at compile time =====
let userAge2: number = 25; // Clearly labeled as a number
let nextYear2: number = userAge2 + 1; // Correct:25 + 1 = 26
console.log(nextYear2); // Output 26
Output:
251
26
"25" + 1 evaluates to "251" instead of 26—this is a pitfall that beginners often fall into. TypeScript uses type checking to help you avoid these kinds of issues at compile time.
5. tsc --watch: Automatic Compilation
It’s too much of a hassle to manually run tsc every time I modify the .ts file. The --watch mode (abbreviated as -w) allows the compiler to monitor file changes and compile as soon as the file is saved:
tsc --watch
Or specify a single file:
tsc src/hello.ts --watch
Once enabled, the terminal will display:
[8:30:15 PM] Starting compilation in watch mode...
[8:30:15 PM] Found 0 errors. Watching for file changes.
Every time you save the file, it automatically recompiles; you just need to focus on the node dist/xxx.js output.
▶ Example: Complete Workflow During Development
# Terminal 1:Enable Automatic Compilation
tsc --watch
# Terminal 2:Run and Test
node dist/hello.js
# Edit src/hello.ts Run it again
node dist/hello.js
ts-node to run the .ts file directly (skipping the manual compilation step): npm install -g ts-node, then ts-node src/hello.ts. This tool is very convenient for learning, but you should still follow the compilation process in a production environment.
6. Type Inference—What Makes TypeScript So Smart
You may have noticed that not all variables require a type annotation. TypeScript is smart enough to automatically infer the type of a variable based on its initial value:
let name = "Diana"; // TS Inferred type: string
let age = 20; // TS Inferred type: number
let isActive = true; // TS Inferred type: boolean
This is completely equivalent to the following code:
let name: string = "Diana";
let age: number = 20;
let isActive: boolean = true;
The rule is simple: when an initial value is provided, TypeScript can infer the type, so you can omit the type annotation; when no initial value is provided, you must explicitly specify the type.
▶ Example: When Must You Include a Type Annotation?
// ✅ Has an initial value——Type can be inferred,Comments may be omitted
let message = "Hello";
let count = 0;
// ❌ No initial value——The type must be specified.,Otherwise TS The default is any
let userId: number; // Must be labeled
let userEmail: string; // Must be labeled
// ❌ Do not label = Implicit any(strict An error occurs in this mode)
let userId2; // ❌ Error:Variables implicitly have"any"Type
Output:
Error: Variable 'userId2' implicitly has an 'any' type.
strict: true mode, variables without initial values or type annotations will result in an error. This is a good thing—it forces you to explicitly specify the type of each variable, preventing ambiguous any from popping up everywhere.
❓ FAQ
var instead of let?target setting in tsconfig.json. If you set target to ES5 (a very old version), the compiler will convert let and const to var to ensure compatibility. Setting it to ES2020 or higher will preserve let and const. We recommend setting it to ES2020.node dist/xxx.js every time. Is there an easier way?npm install -g ts-node), you can simply run ts-node src/xxx.ts to skip the manual compilation step. The Code Runner extension for VS Code also supports one-click execution of TS files. However, for production projects, we still recommend following the tsc compilation process.📖 Summary
- Type annotation syntax:
let variableName: type = value; function parameters and return values can also be annotated - TypeScript performs type erasure after compilation, so the generated JavaScript code does not contain type information.
- The core value of TypeScript: Detecting type errors at compile time to prevent runtime issues
tsc --watchCompile automatically,ts-nodeRun TS files directly- Type inference eliminates the need to manually annotate variables with initial values, but variables without initial values must be annotated.
- Implicit
anyin strict mode will throw an error, which is a good thing—it forces you to specify the type clearly.
📝 Exercises
- Basic Exercise (Difficulty ⭐): Create
src/hello.ts, define three variables with type annotations (string, number, boolean), compile and run the program, then useconsole.logto print their values. - Advanced Problem (Difficulty ⭐⭐): Write a type-annotated function
calculateArea(width: number, height: number): numberthat calculates the area of a rectangle. Intentionally pass a string parameter to it, observe the TypeScript compilation error message, and then fix the error. - Challenge (Difficulty: ⭐⭐⭐): Compare how JavaScript and TypeScript handle the same set of error codes—write a piece of JavaScript code containing three types of errors (treating a string as a number, calling a nonexistent method, and accessing an undefined property), then rewrite it in TypeScript, noting on which line TypeScript reports each error.