

Picture by Creator
# Introduction
You’ve got been coding in Python for some time, completely find it irresistible, and might in all probability write decorators in your sleep. However there’s this nagging voice in your head saying it’s best to study TypeScript. Perhaps it is for that full-stack function, or maybe you are bored with explaining why Python is “completely wonderful” for giant codebases.
Here is the factor: TypeScript is not simply “JavaScript with varieties.” It is what JavaScript ought to have been from the beginning. And in case you’re coming from Python, you already perceive greater than you assume.
# Going from Python to TypeScript
Python provides you duck typing and dynamic flexibility. TypeScript provides you a similar flexibility with a security internet. Consider it as Python’s mypy if mypy truly labored in every single place.
In Python, you possibly can name any methodology on any object and “hope” it really works. TypeScript tells you at compile time whether or not it should work, saving you from these "AttributeError: 'NoneType' object has no attribute 'title'"
moments.
# Python: You hope this works
def process_user(person):
return person.title.higher()
// TypeScript: You already know this works
operate processUser(person: Person): string {
return person.title.toUpperCase();
}
If person
does not have a title
property, TypeScript catches it earlier than your code ever runs. So you do not want defensive if hasattr(obj, 'attribute')
checks in every single place.
# TypeScript Fundamentals
Let’s begin with the fundamentals of TypeScript.
// Variables and Primary Varieties
Python’s kind hints are elective options. TypeScript’s varieties are extra like enforced contracts. The excellent news? TypeScript can infer most varieties mechanically, so that you need not annotate all the pieces.
# Python
title = "Alice"
age = 30
is_active = True
scores = [95, 87, 92]
person = {"title": "Bob", "age": 25}
// TypeScript
const title = "Alice"; // string (inferred)
const age = 30; // quantity (inferred)
const isActive = true; // boolean (inferred)
const scores = [95, 87, 92]; // quantity[] (inferred)
const person = { title: "Bob", age: 25 }; // object (inferred)
// Or be specific
const title: string = "Alice";
const scores: quantity[] = [95, 87, 92];
You solely want specific annotations when the inference is not apparent or whenever you need to be further clear about your intentions.
// Features
Perform syntax maps nearly immediately, however TypeScript’s method to default parameters is cleaner than Python’s mutable default argument gotchas.
# Python
def greet(title: str, excited: bool = False) -> str:
suffix = "!" if excited else "."
return f"Good day, {title}{suffix}"
// TypeScript
operate greet(title: string, excited = false): string {
const suffix = excited ? "!" : ".";
return `Good day, ${title}${suffix}`;
}
// Or arrow operate (Python lambda equal)
const greet = (title: string, excited = false): string =>
`Good day, ${title}${excited ? "!" : "."}`;
The arrow operate syntax is just like Python’s lambda, however extra highly effective. You may write full operate our bodies or concise one-liners. Template literals (these backticks) work identical to Python’s f-strings.
// Lessons
TypeScript courses really feel extra streamlined than Python courses. No extra self
in every single place, and constructor parameters can mechanically change into properties.
# Python
class Person:
def __init__(self, title: str, electronic mail: str):
self.title = title
self.electronic mail = electronic mail
def greet(self) -> str:
return f"Hello, I am {self.title}"
// TypeScript
class Person {
constructor(public title: string, public electronic mail: string) {}
greet(): string {
return `Hello, I am ${this.title}`;
}
}
That public
key phrase within the constructor is TypeScript’s shorthand for “create this property mechanically and assign the parameter worth to it.” So that you don’t have to make use of the self.title = title
boilerplate. You too can use non-public
or protected
for encapsulation.
# The place TypeScript Will get Fascinating
That is the place TypeScript begins to really feel fascinating as you progress past the fundamentals.
// Union Varieties (Python’s Union
however higher)
Python’s Union varieties from the typing module work, however they’re generally verbose. TypeScript’s union varieties are constructed into the language.
# Python
from typing import Union
def process_id(user_id: Union[str, int]) -> str:
return str(user_id)
// TypeScript
operate processId(userId: string | quantity): string {
return userId.toString();
}
The |
syntax is cleaner than Union[str, int]
, and TypeScript’s compiler can carry out extra subtle kind checking. It is aware of which strategies can be found primarily based on the particular kind at runtime.
// Literal Varieties
Python’s Literal varieties are comparatively new however useful. TypeScript, nevertheless, has far more efficient literal varieties.
# Python
from typing import Literal
Standing = Literal["pending", "approved", "rejected"]
def update_status(standing: Standing) -> None:
print(f"Standing: {standing}")
// TypeScript
kind Standing = "pending" | "accepted" | "rejected";
operate updateStatus(standing: Standing): void {
console.log(`Standing: ${standing}`);
}
Attempt to cross an invalid string like “perhaps” to updateStatus
, and TypeScript will refuse to compile. Your editor will even present autocomplete for the legitimate choices. It is like having an enum that is truly helpful.
// Interfaces
Python’s dataclasses are nice for creating structured information:
# Python
from dataclasses import dataclass
@dataclass
class Person:
title: str
electronic mail: str
age: int
However interfaces in TypeScript are extra versatile. They describe the info with out creating a selected class implementation.
// TypeScript
interface Person {
title: string;
electronic mail: string;
age: quantity;
}
// Use it anyplace
const person: Person = { title: "Alice", electronic mail: "[email protected]", age: 30 };
Any object that has the correct properties mechanically satisfies the interface. No inheritance required, no specific class instantiation wanted. It is duck typing with compile-time verification.
# Studying Extra TypeScript Options
Now let’s study a number of extra helpful options of TypeScript.
// Generics (Like Python’s TypeVar
)
Python’s generic typing works, but it surely’s clunky. TypeScript generics really feel pure and highly effective proper out of the field.
# Python
from typing import TypeVar, Checklist
T = TypeVar('T')
def first(gadgets: Checklist[T]) -> T:
return gadgets[0]
// TypeScript
operate first(gadgets: T[]): T {
return gadgets[0];
}
// Works with something
const firstNumber = first([1, 2, 3]); // quantity
const firstString = first(["a", "b", "c"]); // string
TypeScript mechanically infers the generic kind from utilization. Name first
with numbers, and it returns a quantity. Name it with strings, and it returns a string. No specific kind parameters wanted, however you possibly can present them when the inference is not clear.
// Sort Guards
Sort guards allow you to write runtime checks that the compiler understands and makes use of to slim varieties in subsequent code.
operate isString(worth: unknown): worth is string {
return typeof worth === "string";
}
operate processValue(worth: string | quantity) {
if (isString(worth)) {
return worth.toUpperCase();
}
return worth.toFixed(2);
}
The worth is string
syntax tells TypeScript that if this operate returns true, the parameter is certainly a string. Contained in the if block, you get full string strategies and properties. No casting, no assertions, simply sensible kind narrowing primarily based in your runtime checks.
// Mapped Varieties (Checklist Comprehensions for Varieties)
Consider mapped varieties as record comprehensions, however for kind transformations. They allow you to create new varieties by remodeling present ones.
kind Person = {
title: string;
electronic mail: string;
age: quantity;
};
// Make all properties elective
kind PartialUser = Partial;
// Make all properties readonly
kind ReadonlyUser = Readonly;
// Choose particular properties
kind UserContact = Choose;
These utility varieties ship with TypeScript and clear up widespread patterns. For those who want a kind that is like Person however with elective fields for updates, you should utilize Partial
. And if it’s worthwhile to guarantee no modifications after creation, use Readonly
.
# Error Dealing with in TypeScript
Python builders love attempt/besides blocks, however they will get verbose. TypeScript makes use of a distinct method utilizing consequence varieties and union varieties for error dealing with that make errors specific in your operate signatures:
// Consequence kind sample (impressed by Rust)
kind Consequence = { success: true; information: T } | { success: false; error: E };
// Make this file a module
export {};
// Assuming you might have a Person kind and parseUser operate
interface Person {
title: string;
// ... different properties
}
operate parseUser(information: unknown): Person {
// Your parsing logic right here
// This could throw an error if parsing fails
if (!information || typeof information !== 'object') {
throw new Error('Invalid person information');
}
const person = information as any;
if (!person.title || typeof person.title !== 'string') {
throw new Error('Person title is required and have to be a string');
}
return { title: person.title };
}
async operate safeParseUser(information: unknown): Promise> {
attempt {
const person = parseUser(information);
return { success: true, information: person };
} catch (error) {
// Repair: Deal with the case the place error won't have a message property
const errorMessage = error instanceof Error ? error.message : String(error);
return { success: false, error: errorMessage };
}
}
You need to use it like so:
// Utilization (wrapped in an async operate or use at prime stage in a module)
async operate instance() {
const rawData = { title: "John Doe" }; // Instance information
const consequence = await safeParseUser(rawData);
if (consequence.success) {
console.log(consequence.information.title); // TypeScript is aware of that is Person
} else {
console.error(consequence.error); // TypeScript is aware of that is string
}
}
// Name the instance operate
instance();
This sample makes errors specific within the kind system. As a substitute of exceptions flying round invisibly, errors change into a part of the return kind. The Consequence
kind forces you to deal with each success and failure instances. TypeScript’s discriminated unions make this sample easy: the success property tells which department of the union you are in, so it is aware of whether or not information or error is obtainable.
# Conclusion
TypeScript is changing into tremendous in style in net improvement, large-scale functions, and anyplace you want sturdy APIs.
The transition is not about studying a brand new language. It is extra about making use of all the pieces you realize about good software program design in a distinct ecosystem. Your Python instinct for clear code, readable APIs, and considerate abstractions interprets immediately.
So open VS Code, create a .ts
file, and begin coding. The worst factor that occurs? You study one thing new. One of the best factor? You would possibly simply discover your new favourite language. Blissful coding!
Bala Priya C is a developer and technical author from India. She likes working on the intersection of math, programming, information science, and content material creation. Her areas of curiosity and experience embody DevOps, information science, and pure language processing. She enjoys studying, writing, coding, and low! At present, she’s engaged on studying and sharing her data with the developer group by authoring tutorials, how-to guides, opinion items, and extra. Bala additionally creates partaking useful resource overviews and coding tutorials.