Compare commits
2
Commits
e42d897d41
...
88661ec960
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88661ec960 | ||
|
|
1d9a7fa4fe |
No files matched your search
@@ -0,0 +1,30 @@
|
||||
type State = "locked" | "unlocked";
|
||||
|
||||
class CredentialManager<S extends State> {
|
||||
private readonly state?: S;
|
||||
|
||||
unlock(this: CredentialManager<"locked">, master_key: string) {
|
||||
return this as unknown as CredentialManager<"unlocked">;
|
||||
}
|
||||
|
||||
set(this: CredentialManager<"unlocked">, key: string, value: any) {
|
||||
// ...
|
||||
}
|
||||
|
||||
get(this: CredentialManager<"unlocked">, key: string): string | undefined {
|
||||
// ...
|
||||
return undefined;
|
||||
}
|
||||
|
||||
lock(this: CredentialManager<"unlocked">): CredentialManager<"locked"> {
|
||||
return this as unknown as CredentialManager<"locked">;
|
||||
}
|
||||
}
|
||||
|
||||
function main2() {
|
||||
let pw_locked = new CredentialManager<"locked">();
|
||||
let pw_unlocked = pw_locked.unlock("psst");
|
||||
pw_unlocked.set("foo", "bar");
|
||||
let val = pw_unlocked.get("foo");
|
||||
pw_locked = pw_unlocked.lock();
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class WebSocketClient {
|
||||
}
|
||||
}
|
||||
|
||||
function main_ws() {
|
||||
function main1() {
|
||||
const client = new WebSocketClient();
|
||||
client.send(OpCode.PING, {});
|
||||
}
|
||||
@@ -23,7 +23,7 @@ function navigate<P extends string>(path: P, params: ParseUrlParams<P>) {
|
||||
// ...
|
||||
}
|
||||
|
||||
function main() {
|
||||
function main3() {
|
||||
navigate("/hello", {});
|
||||
navigate("/hello/{name}", { name: "foo" });
|
||||
navigate("/book/{author}/{id}", { author: "foo", id: "bar" });
|
||||
@@ -1,2 +1,3 @@
|
||||
[workspace]
|
||||
members = ["01-problem", "02-runtime-check", "03-builder-pattern", "04-typestate"]
|
||||
resolver = "3"
|
||||
@@ -1,5 +1,54 @@
|
||||
# Type Level Programming
|
||||
|
||||
This repository contains a collection of examples demonstrating various type-level programming patterns in Rust, Go, and TypeScript.
|
||||
|
||||
The goal of these examples is to show how to leverage the type system of a language to enforce invariants at compile-time, reducing the need for runtime checks and making the code more robust and self-documenting.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
The examples are organized by language and complexity.
|
||||
|
||||
### Rust
|
||||
|
||||
The Rust examples demonstrate a progression of state management for a `CredentialManager`:
|
||||
|
||||
- **[01-problem](./01-problem)**: The initial problem where state is not managed, allowing operations in any order.
|
||||
- **[02-runtime-check](./02-runtime-check)**: Adding runtime checks (e.g., `bool` flags) to ensure operations are performed in the correct state.
|
||||
- **[03-builder-pattern](./03-builder-pattern)**: Using separate structs to represent different states, ensuring state transitions are enforced at compile-time.
|
||||
- **[04-typestate](./04-typestate)**: A classic implementation of the Typestate pattern using generics and `PhantomData` to track state.
|
||||
|
||||
### Go
|
||||
|
||||
- **[05-typestate-go-structs](./05-typestate-go-structs)**: Implementing state transitions in Go using separate structs for each state.
|
||||
- **[06-typestate-go-interfaces](./06-typestate-go-interfaces)**: Using interfaces to restrict the available methods based on the current state of the object.
|
||||
|
||||
### TypeScript
|
||||
|
||||
- **[07-typestate-ts](./07-typestate-ts)**: Implementing the Typestate pattern in TypeScript using `this` type parameters to restrict method calls.
|
||||
- **[08-type-mapping](./08-type-mapping)**: Mapping enum values (like opcodes) to specific argument types for type-safe messaging.
|
||||
- **[09-type-programming](./09-type-programming)**: Advanced recursive type parsing to extract parameters from URL string literals at compile-time.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Rust
|
||||
You can run the Rust examples using Cargo from the root directory:
|
||||
```bash
|
||||
# Example: Running the typestate example
|
||||
cargo run -p 04-typestate
|
||||
```
|
||||
|
||||
### Go
|
||||
The Go examples can be run using the Go CLI:
|
||||
```bash
|
||||
go run ./05-typestate-go-structs
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
The TypeScript examples are best viewed in an IDE (like VS Code) to see the type errors and completions. You can also run them using `ts-node`:
|
||||
```bash
|
||||
npx ts-node 07-typestate-ts/main.ts
|
||||
```
|
||||
|
||||
## Sources
|
||||
|
||||
- https://www.emoses.org/posts/resolver-resolved-pattern/
|
||||
|
||||
Reference in new issue
Block a user