Files
it-know-how/typescript/TYPESCRIPT_INTRO.md
T
2026-03-27 12:58:01 +01:00

13 KiB
Executable File

TypeScript Introduction for Python Developers

A practical guide to TypeScript, written for Python developers.


Table of Contents

  1. What is TypeScript?
  2. Strengths & Weaknesses
  3. Typical Use Cases
  4. Basic Syntax
  5. Arrays
  6. Handling Null and Undefined
  7. Strings and Template Literals
  8. Guard Clauses and Validation
  9. Date Handling
  10. Code Style
  11. Quick Reference: Python to TypeScript

What is TypeScript?

TypeScript is a superset of JavaScript that adds static type checking. Your TypeScript code compiles (transpiles) to plain JavaScript, which then runs in browsers, Node.js, or anywhere JavaScript runs.

// TypeScript (what you write)
function greet(name: string): string {
    return `Hello, ${name}`;
}
// JavaScript (what runs)
function greet(name) {
    return "Hello, " + name;
}

The key difference from Python: TypeScript checks types at compile time, while Python checks types at runtime. This means many bugs are caught before your code runs.


Strengths & Weaknesses

Strengths

Benefit Description
Early bug detection Type errors are caught during development, not in production
Better IDE support Autocomplete, inline docs, and refactoring work reliably
Self-documenting code Types serve as living documentation
Safer refactoring Rename a function and the compiler finds all call sites
Gradual adoption Add TypeScript to existing JavaScript projects incrementally

Weaknesses

Drawback Description
Compilation step Requires a build process (though often simple)
Learning curve Advanced types can be complex
Boilerplate Type annotations add extra syntax
Type system limits Complex runtime patterns may not fit static typing easily

Comparison with Python

Aspect TypeScript Python
Typing Static (compile time) Dynamic (runtime)
Type inference Yes (often inferrable) Yes (via type hints)
Null safety Optional (strict mode) Via type hints
Null representation null, undefined None
Execution Compiles to JS Interpreted

Typical Use Cases

TypeScript shines in:

  • Frontend web applications (React, Vue, Angular all support TypeScript)
  • Node.js backends (APIs, microservices)
  • Large codebases where refactoring and maintenance matter
  • Teams where code review and shared understanding are important
  • Projects needing stability (banking, healthcare, enterprise software)

Python still leads in data science, ML/AI, scripting, and rapid prototyping.


Basic Syntax

Variables: const and let

TypeScript uses const for variables that won't be reassigned, and let for those that will. Avoid var.

const apiBase = 'https://api.example.com';  // Cannot be reassigned
let count = 0;                               // Can be reassigned
count = count + 1;

Important: const prevents reassignment but doesn't make objects immutable:

const config = { retries: 2 };
config.retries = 3;     // Allowed: mutating the object
// config = {};        // Error: reassigning the variable

Python comparison:

API_BASE = 'https://api.example.com'  # Convention only, not enforced
count = 0

Functions

Basic function declaration with type annotations:

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

With optional parameters and defaults:

function buildWeeklyPeriods(
    dateRange?: DateRange,
    now = new Date(),
): string[] {
    // ...
}
  • ?: marks a parameter as optional
  • = value provides a default
  • : type declares the return type

Python comparison:

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

def build_weekly_periods(date_range=None, now=None):
    if now is None:
        now = datetime.now()

Type Annotations

Type annotations come after the variable/parameter name (opposite of Python):

const name: string = 'Alice';
const age: number = 30;
const isActive: boolean = true;

Common basic types:

TypeScript Python Description
string str Text
number int / float All numbers
boolean bool True / False
undefined Uninitialized
null None Intentional absence
string[] List[str] Array of strings

Arrays

TypeScript arrays are typed and support the same operations as Python lists.

const parts = [
    { type: 'year', value: '2026' },
    { type: 'month', value: '03' },
    { type: 'day', value: '24' },
];

// Access by index
const first = parts[0];

// Array length
const count = parts.length;

Array Methods: find, filter, map, flatMap

find — Get the first matching element:

const yearPart = parts.find((part) => part.type === 'year');
console.log(yearPart); // { type: 'year', value: '2026' }

Returns undefined if no match found.

Python comparison:

year_part = next((p for p in parts if p['type'] == 'year'), None)

filter — Keep matching elements:

const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter((n) => n % 2 === 0);
console.log(evens); // [2, 4]

map — Transform each element:

const doubled = numbers.map((n) => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

flatMap — Filter and transform in one pass:

const result = periodStarts.flatMap((start, index) => {
    if (!isInRange(start)) {
        return [];  // Drop this element
    }
    return `${start.toISOString()}/${end.toISOString()}`;  // Transform
});

Returning [] removes the element; returning a value keeps it.

Python comparison:

filtered = [s for s in period_starts if in_range(s)]
result = [make_interval(s) for s in filtered]

Slicing and Indexing

const alignedStarts: Date[] = [];

// Slice: from start to before last element
const periodStarts = alignedStarts.slice(0, -1);

// Index access
const start = alignedStarts[index];
const end = alignedStarts[index + 1];

Python comparison:

period_starts = aligned_starts[:-1]
start = aligned_starts[index]
end = aligned_starts[index + 1]

Handling Null and Undefined

TypeScript has two "nothing" values: null (explicitly set) and undefined (not yet assigned). Python only has None.

Optional Chaining ?.

Safely access properties that might not exist:

const user: { profile?: { city?: string } } = {};
const city = user.profile?.city;  // undefined, no crash

Without ?., accessing user.profile.city when profile is undefined would throw an error.

Python comparison:

city = user.profile.city if user and user.profile else None

Nullish Coalescing ??

Provide a fallback only when the value is null or undefined:

const name = maybeName ?? 'anonymous';

Key difference from ||:

'' || 'fallback';   // 'fallback' (empty string is falsy)
'' ?? 'fallback';   // '' (only null/undefined trigger fallback)
0 || 'fallback';    // 'fallback'
0 ?? 'fallback';    // 0

Python comparison:

name = x if x is not None else 'fallback'

Combining Operators for Robust Code

These operators work great together:

const year = parts.find((part) => part.type === 'year')?.value ?? '';

Breaking it down:

  1. find(...) returns undefined if no match
  2. ?.value safely accesses value (or returns undefined)
  3. ?? '' provides a fallback string

This pattern is extremely common in TypeScript code.


Strings and Template Literals

String Literals

const a = 'single quotes';
const b = "double quotes";  // Both are valid
const c = '';               // Empty string

Template Literals

Use backticks for string interpolation:

const year = '2026';
const month = '03';
const day = '24';

const label = `${year}-${month}-${day}`;
console.log(label); // '2026-03-24'

Template literals also support multi-line strings:

const html = `
    <div>
        <h1>Title</h1>
    </div>
`;

Python comparison:

label = f"{year}-{month}-{day}"
html = """
    <div>
        <h1>Title</h1>
    </div>
"""

Guard Clauses and Validation

Guard clauses exit early when conditions are not met:

if (rangeStart !== undefined && rangeEnd !== undefined && rangeStart > rangeEnd) {
    return [];
}
  • !== — strict "not equal" (use this, not !=)
  • === — strict "equal" (use this, not ==)
1 === 1;     // true
1 === '1';   // false (different types)
0 === false; // false (different types)

Always prefer strict equality (=== / !==) to avoid subtle type coercion bugs.

Python comparison:

if range_start is not None and range_end is not None and range_start > range_end:
    return []

Date Handling

Getting Timestamps

const startTime = start.getTime();

Returns milliseconds since Unix epoch (1970-01-01).

Compare timestamps directly:

if (startTime >= rangeStart && startTime <= rangeEnd) {
    // ...
}

Converting to ISO Strings

const interval = `${start.toISOString()}/${end.toISOString()}`;

Output:

2026-03-23T23:00:00.000Z/2026-03-30T22:00:00.000Z

The Z indicates UTC timezone.

Python comparison:

start_ts_ms = int(start_dt.timestamp() * 1000)
interval = f"{start.isoformat()}/{end.isoformat()}"

Code Style

Semicolons

TypeScript/JavaScript allows optional semicolons. Most projects choose one style and stick with it:

// With semicolons (common in TypeScript)
const x = 1;
const y = 2;

// Without semicolons (also valid)
const x = 1
const y = 2

Follow your project's convention. Most TypeScript projects use semicolons.

Equality

Operator Use case
=== Always use for comparisons (strict equality)
!== Always use for comparisons (strict inequality)
== Avoid (allows type coercion)
!= Avoid (allows type coercion)

Robust Patterns

The idiomatic way to safely extract values:

function safePart(parts: Part[], wanted: string): string {
    return parts.find((p) => p.type === wanted)?.value ?? '';
}

This function:

  • Returns undefined if no matching part exists
  • Uses ?. to safely access .value
  • Uses ?? '' to ensure a string is always returned

Quick Reference: Python to TypeScript

Functions

def fn(x: int) -> str:
    return str(x)
function fn(x: number): string {
    return String(x);
}

Lambda / Arrow Functions

lambda x: x + 1
(x) => x + 1

Fallback for Missing Values

value = x if x is not None else 'fallback'
const value = x ?? 'fallback';

String Interpolation

f"{year}-{month}-{day}"
`${year}-${month}-${day}`

Find First Match

next((p for p in parts if p['type'] == 'year'), None)
parts.find((p) => p.type === 'year')

Array Filtering

filtered = [x for x in items if x.active]
const filtered = items.filter((x) => x.active);

Array Mapping

mapped = [x.name for x in items]
const mapped = items.map((x) => x.name);

None Checks

if user and user.profile:
    city = user.profile.city
else:
    city = None
const city = user.profile?.city;

Return Type Annotations

from typing import List

def get_names() -> List[str]:
    return ['Alice', 'Bob']
function getNames(): string[] {
    return ['Alice', 'Bob'];
}

Next Steps

Now that you understand the fundamentals, explore:

  • Interfaces and Types — Define custom shapes for your data
  • Generics — Write reusable functions that work with any type
  • Enums — Define fixed sets of values
  • Modules — Organize code across files
  • TypeScript with React/Vue/Node — Apply these concepts in real frameworks

Based on TypeScript learning notes from the d-fine vault.