- Primitive Types
- Structured Data Type Definitions (Dataclasses, Dictionaries, TypedDict)
- Classes
- Class Property Accessors
- Class Generics
- Class Inheritance
- Enum Definitions
- Type Casting
Data-Types
Change TopicPython Data-Types
TypeScript Data-Types
Structured Data Type Definitions (Dataclasses, Dictionaries, TypedDict)
Python supports structured data using dataclasses
, dictionaries, and TypedDict
.
Using dataclasses (preferred for structured data):
from dataclasses import dataclass from typing import Optional @dataclass class User: id: int name: str email: Optional[str] = None # Optional field user = User(id=1, name="Alice")
Using TypedDict (for dictionary-based structures):
from typing import TypedDict class Product(TypedDict, total=False): # `total=False` makes fields optional id: int name: str price: float category: str item: Product = {"id": 101, "name": "Laptop", "price": 1200.0}
Structured Data Type Definitions (Interfaces, Types)
TypeScript allows defining structured data with interface
or type
. Fields can be optional (?
).
interface User { id: number; name: string; email?: string; // Optional field } const user: User = { id: 1, name: "Alice" };
Alternatively, using type
:
type Product = { id: number; name: string; price: number; category?: string; // Optional field }; const item: Product = { id: 101, name: "Laptop", price: 1200 };
Classes
class Person: def __init__(self, name: str): self.name = name print(f"{self.name} is created") def greet(self): print(f"Hello, my name is {self.name}") def __del__(self): print(f"{self.name} is deleted") person = Person("Alice") person.greet() del person # Explicitly triggering destructor (not always necessary)
Classes
class Person { name: string; constructor(name: string) { this.name = name; console.log(`${this.name} is created`); } greet(): void { console.log(`Hello, my name is ${this.name}`); } // No direct destructor, but `finalize` can be used in specific environments } const person = new Person("Alice"); person.greet(); // Output: // Alice is created // Hello, my name is Alice
Typescript does not have destructors.
Class Property Accessors
class Person: def __init__(self, name): self._name = name # Private attribute convention (_name) @property def name(self): """Getter method""" return self._name @name.setter def name(self, value): """Setter method""" if not value: raise ValueError("Name cannot be empty") self._name = value @name.deleter def name(self): """Deleter method""" print("Deleting name...") del self._name # Usage p = Person("Alice") print(p.name) # Getter: Output -> Alice p.name = "Bob" # Setter print(p.name) # Output -> Bob del p.name # Deleter
Class Property Accessors
class Person { private _name: string; private _age: number; constructor(name: string, age: number) { this._name = name; this._age = age; } // Getter for name get name(): string { return this._name; } // Setter for name set name(newName: string) { if (newName.length < 3) { throw new Error("Name must be at least 3 characters long."); } this._name = newName; } } // Usage const person = new Person("Alice", 25); console.log(person.name); // Getter: Alice person.name = "Bob"; // Setter console.log(person.name); // Getter: Bob
Class Generics
from typing import Generic class Box(Generic[T]): def __init__(self, content: T): self.content = content def get_content(self) -> T: return self.content int_box = Box print(int_box.get_content()) # 10 str_box = Box[str]("Python") print(str_box.get_content()) # "Python"
Class Generics
class Box<T> { private content: T; constructor(content: T) { this.content = content; } getContent(): T { return this.content; } } const intBox = new Box<number>(10); console.log(intBox.getContent()); // 10 const strBox = new Box<string>("TypeScript"); console.log(strBox.getContent()); // "TypeScript"
Class Inheritance
class Animal: def __init__(self, name: str): self.name = name def make_sound(self): print("Some generic animal sound") class Dog(Animal): def __init__(self, name: str): super().__init__(name) # Calls parent constructor def make_sound(self): print("Woof!") dog = Dog("Buddy") dog.make_sound() # "Woof!"
Abstract classes defined using abc
module:
from abc import ABC, abstractmethod class Speakable(ABC): @abstractmethod def speak(self): pass # Must be implemented by subclasses class Robot(Speakable): def speak(self): print("Beep boop!") bot = Robot() bot.speak() # "Beep boop!"
Class Inheritance
class Animal { name: string; constructor(name: string) { this.name = name; } makeSound(): void { console.log("Some generic animal sound"); } } class Dog extends Animal { constructor(name: string) { super(name); // Calls parent constructor } makeSound(): void { console.log("Woof!"); } } const dog = new Dog("Buddy"); dog.makeSound(); // "Woof!"
Classes can also implement interface (pure abstract class):
interface Speakable { speak(): void; } class Robot implements Speakable { speak(): void { console.log("Beep boop!"); } } const bot = new Robot(); bot.speak(); // "Beep boop!"
Abstract classes also supported, with a parial implementation:
abstract class Vehicle { abstract move(): void; // Must be implemented by subclass stop(): void { console.log("Stopping..."); } } class Car extends Vehicle { move(): void { console.log("Driving..."); } } const car = new Car(); car.move(); // "Driving..." car.stop(); // "Stopping..."
Enum Definitions
Python's enum
module allows defining enumerations.
from enum import Enum class Status(Enum): PENDING = "Pending" IN_PROGRESS = "In Progress" COMPLETED = "Completed" current_status = Status.IN_PROGRESS
- Enum values can be strings, numbers, or other types.
Enum Definitions
Enums define a set of named constants.
enum Status { Pending, InProgress, Completed, } const currentStatus: Status = Status.InProgress;
- Enum values default to numeric (starting from 0).
- Custom values can be assigned:
enum Role { User = "USER", Admin = "ADMIN", } const userRole: Role = Role.Admin;
Type Casting in Python
Python supports type casting (type conversion) to convert data from one type to another. It also provides mechanisms for type checking and dynamic type handling.
Explicit Type Conversion : - Python allows explicit type conversion using built-in functions like int()
, float()
, str()
, etc.
# Convert between types a = "42" b = int(a) # Convert string to integer c = float(b) # Convert integer to float d = str(c) # Convert float to string print(a, b, c, d) # Output: "42" 42 42.0 "42"
- Type conversion is explicit and must be performed using the appropriate function.
- Incompatible conversions (e.g., converting a non-numeric string to an integer) will raise a
ValueError
.
Python provides the type()
function to check the type of a variable. For more robust type checking, you can use the isinstance()
function.
x = 42 y = "hello" print(type(x)) # Output: <class 'int'> print(type(y)) # Output: <class 'str'> # Using isinstance() if isinstance(x, int): print("x is an integer") # Output: x is an integer
type()
returns the type of the variable.isinstance()
checks if a variable is an instance of a specific type or a tuple of types.
Python is dynamically typed, meaning variables can hold values of any type, and their type can change at runtime.
x = 42 print(type(x)) # Output: <class 'int'> x = "hello" print(type(x)) # Output: <class 'str'>
You can use isinstance()
in a conditional statement to check and handle types dynamically.
def process_value(value): if isinstance(value, int): print(f"Integer: {value}") elif isinstance(value, str): print(f"String: {value}") else: print("Unknown type") process_value(42) # Output: Integer: 42 process_value("hello") # Output: String: hello process_value(3.14) # Output: Unknown type
Python supports type hints using the typing
module, which allows you to specify the expected types of variables, function arguments, and return values. This is useful for static type checking with tools like mypy
.
from typing import List def add_numbers(a: int, b: int) -> int: return a + b def process_list(items: List[int]) -> None: for item in items: print(item) result = add_numbers(10, 20) process_list([1, 2, 3])
- Type hints do not enforce types at runtime but help with code readability and static analysis.
Type Casting in TypeScript
TypeScript provides mechanisms for type casting to convert between types or assert the type of a value. This is useful when working with dynamic data or narrowing types.
Explicit Type Casting. TypeScript allows explicit type casting using the as
keyword or angle-bracket syntax (<>
).
let value: unknown = "Hello, TypeScript"; // Casting to a string let strLength: number = (value as string).length; console.log(strLength); // Output: 17 // Alternatively, using angle-bracket syntax let strLengthAlt: number = (<string>value).length; console.log(strLengthAlt); // Output: 17
- Use
as
for readability and compatibility with JSX. - Type casting does not perform runtime type checks; it only tells the compiler to treat the value as a specific type.
Type guards are used to narrow down the type of a variable within a block of code. They are often used with typeof
, instanceof
, or custom type-checking functions.
function processValue(value: string | number): void { if (typeof value === "string") { console.log(`String value: ${value.toUpperCase()}`); } else { console.log(`Number value: ${value * 2}`); } } processValue("hello"); // Output: String value: HELLO processValue(42); // Output: Number value: 84
class Animal { makeSound(): void { console.log("Some generic animal sound"); } } class Dog extends Animal { makeSound(): void { console.log("Woof!"); } } function identifyAnimal(animal: Animal): void { if (animal instanceof Dog) { console.log("This is a dog"); } else { console.log("This is some other animal"); } } const dog = new Dog(); identifyAnimal(dog); // Output: This is a dog
Type assertions are used to tell the TypeScript compiler to treat a value as a specific type. This is useful when you know more about the type than the compiler does.
let someValue: unknown = "TypeScript"; // Assert that the value is a string let strLength: number = (someValue as string).length; console.log(strLength); // Output: 10
You can combine type assertions or type guards with conditional statements to handle dynamic types.
function printValue(value: string | number): void { if (typeof value === "string") { console.log(`String: ${value}`); } else { console.log(`Number: ${value}`); } } printValue("Hello"); // Output: String: Hello printValue(123); // Output: Number: 123
You can define custom type guard functions to narrow down types.
interface Cat { meow(): void; } interface Dog { bark(): void; } function isCat(animal: Cat | Dog): animal is Cat { return (animal as Cat).meow !== undefined; } function handleAnimal(animal: Cat | Dog): void { if (isCat(animal)) { animal.meow(); } else { animal.bark(); } } const cat: Cat = { meow: () => console.log("Meow!") }; const dog: Dog = { bark: () => console.log("Woof!") }; handleAnimal(cat); // Output: Meow! handleAnimal(dog); // Output: Woof!