From Zero to AI

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:

  1. Explicit annotation: const greeting: string = "Hello"
  2. 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:

  1. Declaring without initializing
let username: string; // Declare now, assign later
username = 'alice';
  1. Type is not obvious from the value
let id: string | number = 'user_123'; // Could be string or number
  1. 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 width and height as 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:

  1. Has a Product with name, price, and quantity
  2. Has a function calculateTotal that takes a product and returns price * quantity
  3. 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

  1. Type annotations use a colon syntax: let name: string = "Alice"
  2. Type inference lets TypeScript figure out types from values
  3. Function parameters should always have explicit types
  4. Objects can have typed structures with required and optional properties
  5. Arrays are typed with type[] or Array<type> syntax
  6. Error messages are descriptive - read them carefully to fix issues
  7. 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.

Continue to Lesson 2.4: Compilation and Running