Lesson 2.3: First TypeScript Program
Duration: 55 minutes
Learning Objectives
By the end of this lesson, you will be able to:
- Write basic TypeScript code with type annotations
- Understand type inference and when to use explicit types
- Create typed variables, functions, and objects
- Read and understand TypeScript error messages
Your First TypeScript File
Let us create a simple TypeScript program. Create a file called src/index.ts:
// src/index.ts
// Variable with type annotation
const greeting: string = 'Hello, TypeScript!';
// TypeScript infers the type from the value
const year = 2024; // TypeScript knows this is a number
// Print to console
console.log(greeting);
console.log('Current year:', year);
Notice two ways to declare typed variables:
- Explicit annotation:
const greeting: string = "Hello" - Type inference:
const year = 2024(TypeScript figures out it is a number)
Type Annotations Basics
Type annotations tell TypeScript what type a value should be.
Syntax
let variableName: type = value;
Primitive Types
// String - text data
let firstName: string = 'Alice';
let message: string = 'Welcome to TypeScript';
// Number - integers and decimals
let age: number = 25;
let price: number = 99.99;
let negative: number = -10;
// Boolean - true or false
let isActive: boolean = true;
let hasAccess: boolean = false;
When TypeScript Complains
let count: number = 10;
count = 'ten'; // Error! Type 'string' is not assignable to type 'number'
let name: string = 'Bob';
name = 42; // Error! Type 'number' is not assignable to type 'string'
Type Inference
TypeScript is smart. When you assign a value, it often knows the type without you telling it.
// TypeScript infers these types automatically
let city = 'New York'; // inferred as string
let population = 8336817; // inferred as number
let isCapital = false; // inferred as boolean
// You can hover over variables in VS Code to see inferred types
When to Use Explicit Types
Use explicit types when:
- Declaring without initializing
let username: string; // Declare now, assign later
username = 'alice';
- Type is not obvious from the value
let id: string | number = 'user_123'; // Could be string or number
- Function parameters (always)
function greet(name: string) {
console.log('Hello, ' + name);
}
When Inference is Enough
Let TypeScript infer when the type is obvious:
// Clear from the value - no annotation needed
const PI = 3.14159;
const APP_NAME = 'My App';
const MAX_RETRIES = 3;
// Clear from function return
const doubled = [1, 2, 3].map((n) => n * 2); // number[]
Functions with Types
Functions benefit most from explicit types.
Basic Function Types
// Parameter types and return type
function add(a: number, b: number): number {
return a + b;
}
const result = add(5, 3); // result is number
console.log(result); // Output: 8
Return Type Inference
TypeScript can often infer return types:
// Return type inferred as number
function multiply(a: number, b: number) {
return a * b;
}
// Return type inferred as string
function greet(name: string) {
return 'Hello, ' + name;
}
Void Return Type
Functions that do not return anything have a void return type:
function logMessage(message: string): void {
console.log(message);
// No return statement
}
logMessage('This is a log');
Arrow Functions with Types
// Arrow function with types
const divide = (a: number, b: number): number => {
return a / b;
};
// Shorter form for simple expressions
const square = (n: number): number => n * n;
Working with Objects
Objects in TypeScript can have their structure defined.
Object Type Annotations
// Inline object type
const user: { name: string; age: number } = {
name: 'Alice',
age: 30,
};
// Access properties
console.log(user.name); // "Alice"
console.log(user.age); // 30
Object Type Inference
// TypeScript infers the shape
const product = {
name: 'Laptop',
price: 999.99,
inStock: true,
};
// TypeScript knows the structure
console.log(product.name); // OK
console.log(product.colour); // Error! Property 'colour' does not exist
Optional Properties
Use ? to mark properties that might not exist:
const config: { host: string; port?: number } = {
host: 'localhost',
// port is optional, we can skip it
};
console.log(config.host); // "localhost"
console.log(config.port); // undefined (but no error)
Arrays with Types
Arrays can be typed to contain specific element types.
Array Type Syntax
// Two ways to write array types
const numbers: number[] = [1, 2, 3, 4, 5];
const names: Array<string> = ['Alice', 'Bob', 'Charlie'];
// TypeScript enforces element types
numbers.push(6); // OK
numbers.push('seven'); // Error! Argument of type 'string' is not assignable
Array Type Inference
// TypeScript infers the element type
const scores = [85, 90, 78, 92]; // number[]
const fruits = ['apple', 'banana', 'orange']; // string[]
// Mixed arrays get a union type
const mixed = [1, 'two', 3]; // (string | number)[]
Understanding Error Messages
TypeScript errors are descriptive. Let us learn to read them.
Example Error 1: Type Mismatch
let age: number = 'twenty';
Error message:
Type 'string' is not assignable to type 'number'.
Meaning: You declared age as a number but tried to assign a string.
Example Error 2: Missing Property
const user: { name: string; email: string } = {
name: 'Alice',
};
Error message:
Property 'email' is missing in type '{ name: string; }' but required in type '{ name: string; email: string; }'.
Meaning: Your object is missing the required email property.
Example Error 3: Wrong Number of Arguments
function greet(name: string, greeting: string) {
return greeting + ', ' + name;
}
greet('Alice');
Error message:
Expected 2 arguments, but got 1.
Meaning: The function requires 2 parameters but you only provided 1.
Example Error 4: Property Does Not Exist
const user = { name: 'Alice', age: 30 };
console.log(user.email);
Error message:
Property 'email' does not exist on type '{ name: string; age: number; }'.
Meaning: You are trying to access a property that the object does not have.
Practical Example: User Management
Let us create a more complete example:
// src/index.ts
// Define user structure
const createUser = (
name: string,
email: string,
age: number
): { name: string; email: string; age: number; createdAt: Date } => {
return {
name: name,
email: email,
age: age,
createdAt: new Date(),
};
};
// Create users
const alice = createUser('Alice', 'alice@example.com', 28);
const bob = createUser('Bob', 'bob@example.com', 32);
// Function to display user info
const displayUser = (user: { name: string; email: string; age: number }): void => {
console.log(`Name: ${user.name}`);
console.log(`Email: ${user.email}`);
console.log(`Age: ${user.age}`);
console.log('---');
};
// Display users
displayUser(alice);
displayUser(bob);
// Calculate average age
const calculateAverageAge = (users: { age: number }[]): number => {
const totalAge = users.reduce((sum, user) => sum + user.age, 0);
return totalAge / users.length;
};
const averageAge = calculateAverageAge([alice, bob]);
console.log(`Average age: ${averageAge}`);
Exercises
Exercise 1: Type Annotations
Add type annotations to these variables:
let productName = 'Laptop';
let productPrice = 1299.99;
let isAvailable = true;
let tags = ['electronics', 'computers'];
Solution
let productName: string = 'Laptop';
let productPrice: number = 1299.99;
let isAvailable: boolean = true;
let tags: string[] = ['electronics', 'computers'];
Exercise 2: Function Types
Write a function called calculateArea that:
- Takes
widthandheightas number parameters - Returns the area (width * height) as a number
Solution
function calculateArea(width: number, height: number): number {
return width * height;
}
// Test it
console.log(calculateArea(5, 10)); // Output: 50
console.log(calculateArea(3, 7)); // Output: 21
Exercise 3: Object Types
Create a variable called book with this structure:
title(string)author(string)pages(number)isPublished(boolean)
Solution
const book: {
title: string;
author: string;
pages: number;
isPublished: boolean;
} = {
title: 'TypeScript Handbook',
author: 'Microsoft',
pages: 250,
isPublished: true,
};
console.log(book.title); // "TypeScript Handbook"
Exercise 4: Fix the Errors
This code has type errors. Fix them:
let count: number = '10';
function double(value: number): string {
return value * 2;
}
const user: { name: string } = {
name: 'Alice',
age: 25,
};
Solution
// Fix 1: Value should be a number
let count: number = 10;
// Fix 2: Return type should be number
function double(value: number): number {
return value * 2;
}
// Fix 3: Add age to the type
const user: { name: string; age: number } = {
name: 'Alice',
age: 25,
};
Exercise 5: Build a Simple Program
Create a program that:
- Has a
Productwith name, price, and quantity - Has a function
calculateTotalthat takes a product and returns price * quantity - Creates two products and calculates their totals
Solution
// Product type
const product1: { name: string; price: number; quantity: number } = {
name: 'Keyboard',
price: 79.99,
quantity: 2,
};
const product2: { name: string; price: number; quantity: number } = {
name: 'Mouse',
price: 49.99,
quantity: 3,
};
// Calculate total
function calculateTotal(product: { price: number; quantity: number }): number {
return product.price * product.quantity;
}
// Display results
console.log(`${product1.name}: $${calculateTotal(product1)}`);
console.log(`${product2.name}: $${calculateTotal(product2)}`);
const grandTotal = calculateTotal(product1) + calculateTotal(product2);
console.log(`Grand Total: $${grandTotal}`);
Key Takeaways
- Type annotations use a colon syntax:
let name: string = "Alice" - Type inference lets TypeScript figure out types from values
- Function parameters should always have explicit types
- Objects can have typed structures with required and optional properties
- Arrays are typed with
type[]orArray<type>syntax - Error messages are descriptive - read them carefully to fix issues
- Balance annotations and inference - use explicit types when needed, let TypeScript infer when obvious
Resources
| Resource | Type | Description |
|---|---|---|
| TypeScript: Everyday Types | Documentation | Official types guide |
| Type Inference | Documentation | How inference works |
| TypeScript Playground | Tool | Test code online |
Next Lesson
You have written TypeScript code, but how do you actually run it? Let us learn about compilation.