Typhon

Examples you can try.

Each complete source file passes tyc check with v1.0.0-beta.3. Start a project, paste an example into src/main.ty and check it.

Start a project
tyc init hello
cd hello

Nullable values

Narrow an optional value before passing it to a function.

nullable · complete src/main.ty
def find_user(uid: int) -> str?:
    return "ada" if uid == 1 else None

def greet(user: str) -> None:
    print(f"hello, {user}")

def main() -> None:
    let user: str? = find_user(1)
    if user is not None:
        greet(user)

main()

Check with tyc check src/; compile with tyc build. Generated helpers are included in build/ when needed.

Explicit bindings

Use let for a fixed binding and mut for a value you intend to reassign.

bindings · complete src/main.ty
let limit: int = 3
mut attempts: int = 0
attempts += 1
print(attempts < limit)

Check with tyc check src/; compile with tyc build. Generated helpers are included in build/ when needed.

Exhaustive matching

Handle every variant of a sealed union.

matching · complete src/main.ty
class Circle:
    radius: float

class Square:
    side: float

type Shape = Circle | Square

def area(shape: Shape) -> float:
    match shape:
        case Circle(radius):
            return 3.14 * radius * radius
        case Square(side):
            return side * side

Check with tyc check src/; compile with tyc build. Generated helpers are included in build/ when needed.

Errors as values

Propagate a Result inside a function with a matching error type.

errors · complete src/main.ty
def divide(a: int, b: int) -> Result[int, str]:
    if b == 0:
        return Err("division by zero")
    return Ok(a // b)

def calculate() -> Result[int, str]:
    let value: int = divide(10, 2)?
    return Ok(value * 2)

Check with tyc check src/; compile with tyc build. Generated helpers are included in build/ when needed.

Classes become dataclasses

Declare typed fields and let the compiler generate the constructor.

classes · complete src/main.ty
class User:
    name: str
    enabled: bool = True

Check with tyc check src/; compile with tyc build. Generated helpers are included in build/ when needed.

Concurrent fetching

Run independent calls in a task group. This example prints ada: 0 posts.

gather · complete src/main.ty
import asyncio

type UserId = int

class User:
    name: str

class Post:
    title: str

@gatherable
async def fetch_user(uid: UserId) -> User:
    await asyncio.sleep(0)
    return User(name="ada")

@gatherable
async def fetch_posts(uid: UserId) -> list[Post]:
    await asyncio.sleep(0)
    return []

async def dashboard(uid: UserId) -> str:
    gather:
        user = fetch_user(uid)
        posts = fetch_posts(uid)
    return f"{user.name}: {len(posts)} posts"

async def main() -> None:
    print(await dashboard(1))

asyncio.run(main())

Check with tyc check src/; compile with tyc build. Generated helpers are included in build/ when needed.

Configuration boundaries

Validate a port and propagate a failure through an explicit Result.

config · complete src/main.ty
def parse_port(raw: str) -> Result[int, str]:
    if not raw.isdecimal():
        return Err("port must be a number")
    let port: int = int(raw)
    if port < 1 or port > 65535:
        return Err("port must be between 1 and 65535")
    return Ok(port)

def configure(raw_port: str) -> Result[int, str]:
    let port: int = parse_port(raw_port)?
    return Ok(port)

Check with tyc check src/; compile with tyc build. Generated helpers are included in build/ when needed.

Learn the language.

Walk through the rules, with worked examples and emitted Python.