Mindset shift: JavaScript runtime plus TypeScript contracts, not Python with types
Reframe TypeScript as a static contract layer on top of JavaScript rather than a direct extension of Python's typing habits.
by the end of this lesson you can
- →Uses a clear TypeScript object type or union
- →Keeps the JavaScript runtime control flow readable
- →Does not imply the type annotation enforces runtime validation by itself
Overview
Python developers often arrive with experience using annotations, dataclasses, and duck typing. TypeScript can feel familiar at first, but the real shift is understanding that its types guide design and tooling before runtime, while the emitted program is still ordinary JavaScript.
In Python, you often
treat type hints as useful structure around code that still fundamentally runs inside Python's own runtime model.
In TypeScript, the common pattern is
to write JavaScript-shaped code whose contracts are checked by the compiler and editor, while remembering those types do not exist at runtime.
why this difference matters
The first mistake is assuming this is just Python typing in another language. TypeScript changes how you design boundaries and data shapes, but it still inherits JavaScript's runtime behavior, truthiness, and object semantics.
Python
def greet(user: dict[str, str] | None) -> None:
if user:
print(user["name"])TypeScript
function greet(user: { name: string } | null): void {
if (user) {
console.log(user.name);
}
}Deeper comparison
Python version
def load_name(user: dict[str, str] | None) -> str:
if not user:
return "guest"
return user["name"]TypeScript version
function loadName(user: { name: string } | null): string {
if (!user) {
return "guest";
}
return user.name;
}Reflect
What changes once you treat TypeScript as JavaScript with checked contracts instead of as a typed version of Python?
what a strong answer notices
A strong answer mentions erased types, JavaScript runtime semantics still applying, and the compiler helping you design clearer boundaries before the code runs.
Rewrite
Rewrite this Python snippet into TypeScript and make the runtime shape explicit without pretending the type exists at runtime.
Rewrite this Python
def label_user(user: dict[str, str] | None) -> str:
if not user:
return "guest"
return user["name"]what good looks like
- Uses a clear TypeScript object type or union
- Keeps the JavaScript runtime control flow readable
- Does not imply the type annotation enforces runtime validation by itself
Practice
Describe how you would explain TypeScript to an experienced Python developer who thinks type hints and TypeScript annotations work the same way.
success criteria
- Explains compile-time versus runtime clearly
- Mentions that emitted code is still JavaScript
- Avoids collapsing structural typing into ordinary Python duck typing
Common mistakes
- Assuming TypeScript types behave like Python runtime concepts instead of erased static contracts.
- Talking about TypeScript as if it replaces the need to understand JavaScript.
- Treating familiar annotation syntax as proof that the mental model is the same.
takeaways
- ●The first mistake is assuming this is just Python typing in another language. TypeScript changes how you design boundaries and data shapes, but it still inherits JavaScript's runtime behavior, truthiness, and object semantics.
- ●A strong answer mentions erased types, JavaScript runtime semantics still applying, and the compiler helping you design clearer boundaries before the code runs.
- ●Explains compile-time versus runtime clearly