Skip to main content

From Python to TypeScript

You're building an AI chat interface that streams responses token-by-token. Your Python backend handles the agent logic—tool calls, reasoning, memory. But the browser running that chat UI speaks a different language: TypeScript. Every streaming chunk, every user keystroke, every animated typing indicator runs in TypeScript.

The good news: you already know how to program. Python taught you variables, functions, loops, and type hints. TypeScript uses the same concepts with different syntax. This lesson maps your Python knowledge to TypeScript equivalents, so you can read and write TypeScript code by the end.

This isn't about learning programming from scratch. It's about translation—taking mental models you've built and expressing them in a new syntax that browsers understand.

Variable Declarations

Python uses dynamic assignment. TypeScript requires explicit declaration keywords.

Python Variables

# Python: assign directly, type is inferred
name = "Claude"
age = 3
is_active = True

# Python: optional type hints
name: str = "Claude"
age: int = 3
is_active: bool = True

Output:

# These create variables in Python's namespace
# Type hints are optional and don't enforce anything at runtime

TypeScript Variables

TypeScript uses let for mutable variables and const for immutable ones:

// TypeScript: declare with let (mutable)
let name: string = "Claude";
let age: number = 3;
let isActive: boolean = true;

// TypeScript: declare with const (immutable)
const MODEL_NAME: string = "claude-3-opus";
const MAX_TOKENS: number = 4096;

Output:

// Variables are created with explicit mutability
// const prevents reassignment: MODEL_NAME = "gpt-4" would error

Key Differences

ConceptPythonTypeScript
Mutable variablex = 5let x: number = 5
Immutable variableX = 5 (convention)const X: number = 5
Type annotationx: int = 5x: number = 5
Boolean typeboolboolean
No valueNonenull or undefined

TypeScript enforces const at compile time. If you try to reassign a const variable, your code won't compile:

const apiKey: string = "sk-abc123";
apiKey = "sk-xyz789"; // Error: Cannot assign to 'apiKey' because it is constant

Output:

error TS2588: Cannot assign to 'apiKey' because it is a constant.

Type Inference

TypeScript can often infer types from values, just like Python:

// Explicit types
const name: string = "Claude";
const age: number = 3;

// Inferred types (TypeScript figures it out)
const name = "Claude"; // TypeScript knows this is string
const age = 3; // TypeScript knows this is number

Output:

// Both approaches work. Inferred types reduce verbosity.
// Hover over variables in VS Code to see inferred types.

For learning, we'll use explicit types. Once comfortable, you can let TypeScript infer where appropriate.

Function Syntax

Functions are where TypeScript's type system shines. You declare types for parameters and return values.

Python Functions

def greet(name: str) -> str:
return f"Hello, {name}!"

def calculate_tokens(text: str, model: str = "gpt-4") -> int:
# Simplified token estimation
return len(text) // 4

# Calling functions
message = greet("Alice")
tokens = calculate_tokens("Hello, world!")

Output:

Hello, Alice!
3

TypeScript Functions

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

function calculateTokens(text: string, model: string = "gpt-4"): number {
// Simplified token estimation
return Math.floor(text.length / 4);
}

// Calling functions
const message: string = greet("Alice");
const tokens: number = calculateTokens("Hello, world!");
console.log(message);
console.log(tokens);

Output:

Hello, Alice!
3

Syntax Mapping

ElementPythonTypeScript
Function keyworddeffunction
Parameter typename: strname: string
Return type-> str: string (after parentheses)
Default valuemodel: str = "gpt-4"model: string = "gpt-4"
String interpolationf"Hello, {name}"`Hello, ${name}`
Integer division//Math.floor(x / y)

Notice the backticks for template strings in TypeScript. Single or double quotes create regular strings; backticks enable ${variable} interpolation.

Arrow Functions

TypeScript has a concise syntax for functions called arrow functions. They're similar to Python's lambda, but more powerful.

Python Lambda

# Python lambda (limited to single expression)
double = lambda x: x * 2

# Python lambda with type hints (uncommon)
double: Callable[[int], int] = lambda x: x * 2

# Call it
result = double(5) # 10

Output:

10

TypeScript Arrow Functions

// Arrow function with explicit types
const double = (x: number): number => x * 2;

// Arrow function with block body
const processMessage = (text: string): string => {
const cleaned = text.trim();
return cleaned.toLowerCase();
};

// Call them
console.log(double(5)); // 10
console.log(processMessage(" HI ")); // hi

Output:

10
hi

When to Use Arrow Functions

Arrow functions are preferred in TypeScript for:

  • Callbacks and event handlers
  • Array methods like map, filter, reduce
  • Short utility functions
// Array operations with arrow functions
const numbers: number[] = [1, 2, 3, 4, 5];

const doubled = numbers.map((n) => n * 2);
const evens = numbers.filter((n) => n % 2 === 0);
const sum = numbers.reduce((acc, n) => acc + n, 0);

console.log(doubled); // [2, 4, 6, 8, 10]
console.log(evens); // [2, 4]
console.log(sum); // 15

Output:

[2, 4, 6, 8, 10]
[2, 4]
15

Use regular function declarations for top-level functions with names. Use arrow functions for inline expressions.

Control Flow

Control flow syntax differs slightly but maps directly from Python concepts.

If/Else

# Python
score = 85

if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
else:
grade = "C"

print(grade) # B

Output:

B
// TypeScript
const score: number = 85;
let grade: string;

if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else {
grade = "C";
}

console.log(grade); // B

Output:

B

Key differences:

  • Parentheses required around conditions: if (condition)
  • Curly braces for blocks: { } instead of indentation
  • else if instead of elif
  • Semicolons end statements

For Loops

Python's for item in collection becomes TypeScript's for (const item of collection):

# Python
models = ["gpt-4", "claude-3", "gemini"]

for model in models:
print(f"Loading {model}...")

Output:

Loading gpt-4...
Loading claude-3...
Loading gemini...
// TypeScript: for...of iterates values
const models: string[] = ["gpt-4", "claude-3", "gemini"];

for (const model of models) {
console.log(`Loading ${model}...`);
}

Output:

Loading gpt-4...
Loading claude-3...
Loading gemini...

TypeScript has two for-loop variants:

  • for...of — iterates over values (use this for arrays)
  • for...in — iterates over keys/indices (rarely needed)
const models: string[] = ["gpt-4", "claude-3", "gemini"];

// for...of gives values (what you usually want)
for (const model of models) {
console.log(model); // "gpt-4", "claude-3", "gemini"
}

// for...in gives indices (rarely needed)
for (const index in models) {
console.log(index); // "0", "1", "2"
}

Output:

gpt-4
claude-3
gemini
0
1
2

While Loops

# Python
count = 0
while count < 3:
print(f"Attempt {count + 1}")
count += 1

Output:

Attempt 1
Attempt 2
Attempt 3
// TypeScript
let count: number = 0;
while (count < 3) {
console.log(`Attempt ${count + 1}`);
count++;
}

Output:

Attempt 1
Attempt 2
Attempt 3

Note count++ is shorthand for count = count + 1. TypeScript also supports count-- and count += 1.

Equality Operators

TypeScript has two equality operators. Use the strict one.

// Strict equality (===) - use this
console.log(5 === 5); // true
console.log("5" === 5); // false (different types)
console.log(null === undefined); // false

// Loose equality (==) - avoid this
console.log(5 == 5); // true
console.log("5" == 5); // true (type coercion!)
console.log(null == undefined); // true (confusing!)

Output:

true
false
false
true
true
true

Always use === (strict equality) and !== (strict inequality). They compare both value and type, matching Python's behavior.

Quick Reference

PythonTypeScript
x = 5let x: number = 5
X = 5 (constant)const X: number = 5
def f(x: int) -> str:function f(x: number): string { }
lambda x: x * 2(x) => x * 2
f"Hello, {name}"`Hello, ${name}`
for item in items:for (const item of items) { }
if x == 5:if (x === 5) { }
elifelse if
Nonenull or undefined
True / Falsetrue / false
print()console.log()

Try With AI

Prompt 1: Variable Translation

I have this Python code that defines configuration for an AI agent:

api_key = "sk-abc123"
model_name = "gpt-4"
max_tokens = 4096
temperature = 0.7
is_streaming = True

Convert this to TypeScript using const declarations with explicit type annotations.
Which variables should use number vs string vs boolean?

What you're learning: How TypeScript maps Python's dynamic types to explicit type declarations, and when to use const for configuration values that shouldn't change.

Prompt 2: Function Conversion

Convert this Python function to TypeScript with full type annotations:

def format_ai_response(content: str, model: str, tokens_used: int) -> dict:
return {
"content": content,
"model": model,
"tokens": tokens_used,
"timestamp": datetime.now().isoformat()
}

What TypeScript type should I use for the return value?
Should I define a custom type or use a built-in?

What you're learning: How TypeScript handles object return types, and the difference between inline type definitions and named types. This prepares you for defining AI response types in later lessons.

Prompt 3: Loop Refactoring

I have Python code that processes AI responses:

responses = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi there!"},
{"role": "user", "content": "How are you?"}
]

for response in responses:
if response["role"] == "assistant":
print(f"AI: {response['content']}")

Convert this to TypeScript. What type should I use for the responses array?
Should I use for...of or for...in?

What you're learning: How TypeScript handles arrays of objects with specific shapes, and why for...of is the correct choice for iterating values. This pattern appears constantly when processing chat message histories.

Safety note: When experimenting with AI-generated TypeScript, run it through the TypeScript compiler (tsc --noEmit yourfile.ts) to catch type errors before runtime. The compiler is your first line of defense against bugs.