Rust patterns that make your TypeScript actually type-safe
Most TS codebases claim to be "type-safe" but panic at runtime constantly.
Here's how to write TypeScript that borrows Rust's obsession with correctness.
---
1. Result types instead of throwing
Rust doesn't have exceptions. Every error is a value you handle explicitly.
TypeScript has exceptions, but you can choose not to use them.
๐๐๐ (๐ฌ๐ญ๐๐ง๐๐๐ซ๐ ๐๐):
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐ฟ๐๐๐ผ๐๐๐๐ ๐๐บ๐๐๐พ๐ด๐๐พ๐(๐๐๐๐: ๐๐๐๐๐๐): ๐ด๐๐พ๐ {
๐ผ๐๐๐๐ ๐ฝ๐บ๐๐บ =ฬต ๐ฉ๐ฒ๐ฎ๐ญ.๐๐บ๐๐๐พ(๐๐๐๐); // ๐ข๐บ๐ ๐๐๐๐๐
๐๐ฟ (!๐ฝ๐บ๐๐บ.๐พ๐๐บ๐๐
) ๐๐๐๐๐ ๐๐พ๐ ๐ค๐๐๐๐('๐ฌ๐๐๐๐๐๐ ๐พ๐๐บ๐๐
'); // ๐ข๐บ๐ ๐๐๐๐๐
๐๐พ๐๐๐๐ ๐ฝ๐บ๐๐บ;
}
// ๐ข๐บ๐
๐
๐พ๐ ๐๐บ๐ ๐๐ ๐๐ฝ๐พ๐บ ๐๐๐๐ ๐๐๐๐๐๐
๐ผ๐๐๐๐ ๐๐๐พ๐ =ฬต ๐๐บ๐๐๐พ๐ด๐๐พ๐(๐๐๐๐๐);
`
๐๐จ๐จ๐ (๐๐ฎ๐ฌ๐ญ-๐ฌ๐ญ๐ฒ๐ฅ๐):
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐๐๐๐พ ๐ฑ๐พ๐๐๐
๐<๐ณ, ๐ค> =
| { ๐๐: ๐๐๐๐พ; ๐๐บ๐
๐๐พ: ๐ณ }
| { ๐๐: ๐ฟ๐บ๐
๐๐พ; ๐พ๐๐๐๐: ๐ค };
๐ฟ๐๐๐ผ๐๐๐๐ ๐๐บ๐๐๐พ๐ด๐๐พ๐(๐๐๐๐: ๐๐๐๐๐๐): ๐ฑ๐พ๐๐๐
๐<๐ด๐๐พ๐, ๐๐๐๐๐๐> {
๐๐๐ {
๐ผ๐๐๐๐ ๐ฝ๐บ๐๐บ = ๐ฉ๐ฒ๐ฎ๐ญ.๐๐บ๐๐๐พ(๐๐๐๐);
๐๐ฟ (!๐ฝ๐บ๐๐บ.๐พ๐๐บ๐๐
) {
๐๐พ๐๐๐๐ { ๐๐: ๐ฟ๐บ๐
๐๐พ, ๐พ๐๐๐๐: '๐ฌ๐๐๐๐๐๐ ๐พ๐๐บ๐๐
' };
}
๐๐พ๐๐๐๐ { ๐๐: ๐๐๐๐พ, ๐๐บ๐
๐๐พ: ๐ฝ๐บ๐๐บ };
} ๐ผ๐บ๐๐ผ๐ (๐พ) {
๐๐พ๐๐๐๐ { ๐๐: ๐ฟ๐บ๐
๐๐พ, ๐พ๐๐๐๐: '๐จ๐๐๐บ๐
๐๐ฝ ๐ฉ๐ฒ๐ฎ๐ญ' };
}
}
// ๐ข๐๐๐๐๐
๐พ๐ ๐ฟ๐๐๐ผ๐พ๐ ๐๐๐ ๐๐ ๐๐บ๐๐ฝ๐
๐พ ๐ป๐๐๐ ๐ผ๐บ๐๐พ๐
๐ผ๐๐๐๐ ๐๐พ๐๐๐
๐ = ๐๐บ๐๐๐พ๐ด๐๐พ๐(๐๐๐๐๐);
๐๐ฟ (๐๐พ๐๐๐
๐.๐๐) {
๐ผ๐๐๐๐๐
๐พ.๐
๐๐(๐๐พ๐๐๐
๐.๐๐บ๐
๐๐พ.๐พ๐๐บ๐๐
);
} ๐พ๐
๐๐พ {
๐ผ๐๐๐๐๐
๐พ.๐พ๐๐๐๐(๐๐พ๐๐๐
๐.๐พ๐๐๐๐);
}
`
Now errors are in the type signature. You can't ignore them.
---
2. Option types for nullable values
Rust has `Option<T>` for "maybe exists, maybe doesn't."
TypeScript has `T | null | undefined` but people handle it inconsistently.
๐๐๐:
`typescript
function findUser(id: string): User | null {
return db.get(id) ?? null;
}
const user = findUser('123');
console.log(
user.email); // Runtime error if null
`
๐๐จ๐จ๐:
`typescript
type Option<T> =
| { some: true; value: T }
| { some: false };
function findUser(id: string): Option<User> {
const user = db.get(id);
return user
? { some: true, value: user }
: { some: false };
}
const result = findUser('123');
if (result.some) {
console.log(
result.value.email); // Type-safe
} else {
console.log('User not found');
}
`
Can't access `.value` without checking `.some` first.
---
3. Exhaustive pattern matching
Rust's `match` forces you to handle every case.
TypeScript's `switch` doesn't. You can forget cases silently.
๐๐๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐๐๐๐พ ๐ฒ๐๐บ๐๐๐ = '๐๐พ๐๐ฝ๐๐๐' | '๐๐๐ผ๐ผ๐พ๐๐' | '๐พ๐๐๐๐';
๐ฟ๐๐๐ผ๐๐๐๐ ๐๐บ๐๐ฝ๐
๐พ๐ฒ๐๐บ๐๐๐(๐๐๐บ๐๐๐: ๐ฒ๐๐บ๐๐๐) {
๐๐๐๐๐ผ๐ (๐๐๐บ๐๐๐) {
๐ผ๐บ๐๐พ '๐๐พ๐๐ฝ๐๐๐':
๐๐พ๐๐๐๐ '๐ซ๐๐บ๐ฝ๐๐๐...';
๐ผ๐บ๐๐พ '๐๐๐ผ๐ผ๐พ๐๐':
๐๐พ๐๐๐๐ '๐ฃ๐๐๐พ!';
// ๐ฅ๐๐๐๐๐ '๐พ๐๐๐๐' - ๐ผ๐๐๐๐๐
๐พ๐ ๐ฟ๐๐๐พ, ๐ป๐๐พ๐บ๐๐ ๐บ๐ ๐๐๐๐๐๐๐พ
}
}
`
๐๐จ๐จ๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐ฟ๐๐๐ผ๐๐๐๐ ๐๐บ๐๐ฝ๐
๐พ๐ฒ๐๐บ๐๐๐(๐๐๐บ๐๐๐: ๐ฒ๐๐บ๐๐๐): ๐๐๐๐๐๐ {
๐๐๐๐๐ผ๐ (๐๐๐บ๐๐๐) {
๐ผ๐บ๐๐พ '๐๐พ๐๐ฝ๐๐๐':
๐๐พ๐๐๐๐ '๐ซ๐๐บ๐ฝ๐๐๐...';
๐ผ๐บ๐๐พ '๐๐๐ผ๐ผ๐พ๐๐':
๐๐พ๐๐๐๐ '๐ฃ๐๐๐พ!';
๐ผ๐บ๐๐พ '๐พ๐๐๐๐':
๐๐พ๐๐๐๐ '๐ฅ๐บ๐๐
๐พ๐ฝ!';
๐ฝ๐พ๐ฟ๐บ๐๐
๐:
๐ผ๐๐๐๐ _๐พ๐๐๐บ๐๐๐๐๐๐พ: ๐๐พ๐๐พ๐ = ๐๐๐บ๐๐๐;
๐๐๐๐๐ ๐๐พ๐ ๐ค๐๐๐๐(`๐ด๐๐๐บ๐๐ฝ๐
๐พ๐ฝ ๐๐๐บ๐๐๐: ${_๐พ๐๐๐บ๐๐๐๐๐๐พ}`);
}
}
`
Add a new status? TypeScript errors until you handle it.
---
4. Branded types for validation
Rust newtypes prevent mixing incompatible types.
TypeScript's structural typing lets you pass any string anywhere.
๐๐๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐ฟ๐๐๐ผ๐๐๐๐ ๐๐พ๐๐ฝ๐ค๐๐บ๐๐
(๐พ๐๐บ๐๐
: ๐๐๐๐๐๐) { ... }
๐ฟ๐๐๐ผ๐๐๐๐ ๐ฝ๐พ๐
๐พ๐๐พ๐ด๐๐พ๐(๐๐๐พ๐๐จ๐ฝ: ๐๐๐๐๐๐) { ... }
๐ผ๐๐๐๐ ๐พ๐๐บ๐๐
= '๐๐๐พ๐@๐พ๐๐บ๐๐๐
๐พ.๐ผ๐๐';
๐ฝ๐พ๐
๐พ๐๐พ๐ด๐๐พ๐(๐พ๐๐บ๐๐
); // ๐ข๐๐๐๐๐
๐พ๐ ๐ฟ๐๐๐พ. ๐ฃ๐๐๐บ๐๐๐พ๐.
`
๐๐จ๐จ๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐๐๐๐พ ๐ค๐๐บ๐๐
= ๐๐๐๐๐๐ & { ๐๐พ๐บ๐ฝ๐๐๐
๐ __๐ป๐๐บ๐๐ฝ: '๐ค๐๐บ๐๐
' };
๐๐๐๐พ ๐ด๐๐พ๐๐จ๐ฝ = ๐๐๐๐๐๐ & { ๐๐พ๐บ๐ฝ๐๐๐
๐ __๐ป๐๐บ๐๐ฝ: '๐ด๐๐พ๐๐จ๐ฝ' };
๐ฟ๐๐๐ผ๐๐๐๐ ๐ค๐๐บ๐๐
(๐: ๐๐๐๐๐๐): ๐ค๐๐บ๐๐
| ๐๐๐
๐
{
๐๐พ๐๐๐๐ ๐.๐๐๐ผ๐
๐๐ฝ๐พ๐('@') ? ๐ ๐บ๐ ๐ค๐๐บ๐๐
: ๐๐๐
๐
;
}
๐ฟ๐๐๐ผ๐๐๐๐ ๐ด๐๐พ๐๐จ๐ฝ(๐: ๐๐๐๐๐๐): ๐ด๐๐พ๐๐จ๐ฝ {
๐๐พ๐๐๐๐ ๐ ๐บ๐ ๐ด๐๐พ๐๐จ๐ฝ;
}
๐ฟ๐๐๐ผ๐๐๐๐ ๐๐พ๐๐ฝ๐ค๐๐บ๐๐
(๐พ๐๐บ๐๐
: ๐ค๐๐บ๐๐
) { ... }
๐ฟ๐๐๐ผ๐๐๐๐ ๐ฝ๐พ๐
๐พ๐๐พ๐ด๐๐พ๐(๐๐๐พ๐๐จ๐ฝ: ๐ด๐๐พ๐๐จ๐ฝ) { ... }
๐ผ๐๐๐๐ ๐พ๐๐บ๐๐
= ๐ค๐๐บ๐๐
('๐๐๐พ๐@๐พ๐๐บ๐๐๐
๐พ.๐ผ๐๐')!;
๐ผ๐๐๐๐ ๐๐๐พ๐๐จ๐ฝ = ๐ด๐๐พ๐๐จ๐ฝ('๐ฃ๐ค๐ฅ');
๐ฝ๐พ๐
๐พ๐๐พ๐ด๐๐พ๐(๐พ๐๐บ๐๐
); // ๐ณ๐๐๐พ ๐พ๐๐๐๐! ๐ข๐บ๐'๐ ๐๐๐ ๐๐๐พ๐.
`
Primitive types but compiler-enforced separation.
---
5. Builder pattern for complex construction
Rust uses builders for objects with many optional fields.
TypeScript just has massive option objects that nobody validates.
๐๐๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐๐๐๐พ๐๐ฟ๐บ๐ผ๐พ ๐ข๐๐๐ฟ๐๐ {
๐๐๐๐?: ๐๐๐๐๐๐;
๐๐๐๐?: ๐๐๐๐ป๐พ๐;
๐๐๐๐พ๐๐๐?: ๐๐๐๐ป๐พ๐;
๐๐พ๐๐๐๐พ๐?: ๐๐๐๐ป๐พ๐;
}
// ๐ถ๐๐บ๐'๐ ๐๐พ๐๐๐๐๐พ๐ฝ? ๐ถ๐๐บ๐ ๐บ๐๐พ ๐๐๐พ ๐ฝ๐พ๐ฟ๐บ๐๐
๐๐? ๐ถ๐๐ ๐๐๐๐๐.
๐ผ๐๐๐๐ ๐ผ๐๐๐ฟ๐๐: ๐ข๐๐๐ฟ๐๐ = { ๐๐๐๐: '๐
๐๐ผ๐บ๐
๐๐๐๐' };
`
๐๐จ๐จ๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐ผ๐
๐บ๐๐ ๐ข๐๐๐ฟ๐๐๐ก๐๐๐
๐ฝ๐พ๐ {
๐๐๐๐๐บ๐๐พ ๐๐๐๐ = '๐
๐๐ผ๐บ๐
๐๐๐๐';
๐๐๐๐๐บ๐๐พ ๐๐๐๐ = ๐ช๐ข๐ช๐ข;
๐๐๐๐๐บ๐๐พ ๐๐๐๐พ๐๐๐ = ๐ง๐ข๐ข๐ข;
๐๐๐๐๐บ๐๐พ ๐๐พ๐๐๐๐พ๐ = ๐ฅ;
๐๐พ๐๐ง๐๐๐(๐๐๐๐: ๐๐๐๐๐๐): ๐๐๐๐ {
๐๐๐๐.๐๐๐๐ = ๐๐๐๐;
๐๐พ๐๐๐๐ ๐๐๐๐;
}
๐๐พ๐๐ฏ๐๐๐(๐๐๐๐: ๐๐๐๐ป๐พ๐): ๐๐๐๐ {
๐๐ฟ (๐๐๐๐ < ๐ข || ๐๐๐๐ > ๐จ๐ง๐ง๐ฅ๐ง) {
๐๐๐๐๐ ๐๐พ๐ ๐ค๐๐๐๐('๐จ๐๐๐บ๐
๐๐ฝ ๐๐๐๐');
}
๐๐๐๐.๐๐๐๐ = ๐๐๐๐;
๐๐พ๐๐๐๐ ๐๐๐๐;
}
๐๐พ๐๐ณ๐๐๐พ๐๐๐(๐๐: ๐๐๐๐ป๐พ๐): ๐๐๐๐ {
๐๐๐๐.๐๐๐๐พ๐๐๐ = ๐๐;
๐๐พ๐๐๐๐ ๐๐๐๐;
}
๐ป๐๐๐
๐ฝ(): ๐ข๐๐๐ฟ๐๐ {
๐๐พ๐๐๐๐ {
๐๐๐๐: ๐๐๐๐.๐๐๐๐,
๐๐๐๐: ๐๐๐๐.๐๐๐๐,
๐๐๐๐พ๐๐๐: ๐๐๐๐.๐๐๐๐พ๐๐๐,
๐๐พ๐๐๐๐พ๐: ๐๐๐๐.๐๐พ๐๐๐๐พ๐
};
}
}
๐ผ๐๐๐๐ ๐ผ๐๐๐ฟ๐๐ = ๐๐พ๐ ๐ข๐๐๐ฟ๐๐๐ก๐๐๐
๐ฝ๐พ๐()
.๐๐พ๐๐ง๐๐๐('๐บ๐๐.๐พ๐๐บ๐๐๐
๐พ.๐ผ๐๐')
.๐๐พ๐๐ฏ๐๐๐(๐ฆ๐ฆ๐ฅ)
.๐ป๐๐๐
๐ฝ();
`
Defaults clear. Validation enforced. Immutable result.
---
6. No silent coercion
Rust doesn't let you compare different types.
TypeScript does. And it's a footgun.
๐๐๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐ผ๐๐๐๐ ๐ผ๐๐๐๐ = '๐ง';
๐๐ฟ (๐ผ๐๐๐๐ > ๐ฅ) { // '๐ง' > ๐ฅ ๐๐ ๐๐๐๐พ (๐๐๐๐๐๐ ๐ผ๐๐๐๐บ๐๐๐๐๐)
๐ผ๐๐๐๐๐
๐พ.๐
๐๐('๐ฌ๐๐๐พ ๐๐๐บ๐ ๐ฅ');
}
`
๐๐จ๐จ๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
// ๐ค๐๐บ๐ป๐
๐พ ๐๐๐๐๐ผ๐ ๐๐๐ฝ๐พ ๐๐ ๐๐๐ผ๐๐๐ฟ๐๐.๐๐๐๐
{
"๐ผ๐๐๐๐๐
๐พ๐๐ฎ๐๐๐๐๐๐": {
"๐๐๐๐๐ผ๐": ๐๐๐๐พ,
"๐๐๐๐๐ผ๐๐ญ๐๐
๐
๐ข๐๐พ๐ผ๐๐": ๐๐๐๐พ,
"๐๐๐จ๐๐๐
๐๐ผ๐๐๐ ๐๐": ๐๐๐๐พ
}
}
๐ผ๐๐๐๐ ๐ผ๐๐๐๐: ๐๐๐๐ป๐พ๐ = ๐๐บ๐๐๐พ๐จ๐๐('๐ง', ๐ฃ๐ข);
๐๐ฟ (๐ผ๐๐๐๐ > ๐ฅ) { // ๐ญ๐๐ ๐๐'๐ ๐บ๐ผ๐๐๐บ๐
๐
๐ ๐ผ๐๐๐๐บ๐๐๐๐ ๐๐๐๐ป๐พ๐๐
๐ผ๐๐๐๐๐
๐พ.๐
๐๐('๐ฌ๐๐๐พ ๐๐๐บ๐ ๐ฅ');
}
`
Strict mode catches this. Always use it.
---
7. Immutable by default
Rust requires `mut` to make things mutable.
TypeScript lets everything mutate unless you say otherwise.
๐๐๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐๐๐๐พ๐๐ฟ๐บ๐ผ๐พ ๐ด๐๐พ๐ {
๐๐ฝ: ๐๐๐๐๐๐;
๐๐บ๐๐พ: ๐๐๐๐๐๐;
}
๐ผ๐๐๐๐ ๐๐๐พ๐: ๐ด๐๐พ๐ = { ๐๐ฝ: '๐ฃ', ๐๐บ๐๐พ: '๐ ๐
๐๐ผ๐พ' };
๐๐๐พ๐.๐๐บ๐๐พ = '๐ก๐๐ป'; // ๐ฌ๐๐๐บ๐๐พ๐. ๐ญ๐ ๐๐บ๐๐๐๐๐.
`
๐๐จ๐จ๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐๐๐๐พ๐๐ฟ๐บ๐ผ๐พ ๐ด๐๐พ๐ {
๐๐พ๐บ๐ฝ๐๐๐
๐ ๐๐ฝ: ๐๐๐๐๐๐;
๐๐พ๐บ๐ฝ๐๐๐
๐ ๐๐บ๐๐พ: ๐๐๐๐๐๐;
}
๐ผ๐๐๐๐ ๐๐๐พ๐: ๐ด๐๐พ๐ = { ๐๐ฝ: '๐ฃ', ๐๐บ๐๐พ: '๐ ๐
๐๐ผ๐พ' };
๐๐๐พ๐.๐๐บ๐๐พ = '๐ก๐๐ป'; // ๐ณ๐๐๐พ ๐พ๐๐๐๐
// ๐ฎ๐ ๐๐๐พ ๐ฑ๐พ๐บ๐ฝ๐๐๐
๐ ๐๐๐๐
๐๐๐
๐๐๐๐พ ๐ด๐๐พ๐ = ๐ฑ๐พ๐บ๐ฝ๐๐๐
๐<{
๐๐ฝ: ๐๐๐๐๐๐;
๐๐บ๐๐พ: ๐๐๐๐๐๐;
}>;
`
Make mutation explicit, not the default.
---
8. Phantom types for state machines
Rust uses phantom types to track state at compile time.
TypeScript can do this too, but almost nobody does.
๐๐๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐ผ๐
๐บ๐๐ ๐ข๐๐๐๐พ๐ผ๐๐๐๐ {
๐๐๐๐๐บ๐๐พ ๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ = ๐ฟ๐บ๐
๐๐พ;
๐ผ๐๐๐๐พ๐ผ๐() { ๐๐๐๐.๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ = ๐๐๐๐พ; }
๐๐พ๐๐ฝ(๐ฝ๐บ๐๐บ: ๐๐๐๐๐๐) {
๐๐ฟ (!๐๐๐๐.๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ) ๐๐๐๐๐ ๐๐พ๐ ๐ค๐๐๐๐('๐ญ๐๐ ๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ');
// ...
}
}
๐ผ๐๐๐๐ ๐ผ๐๐๐ = ๐๐พ๐ ๐ข๐๐๐๐พ๐ผ๐๐๐๐();
๐ผ๐๐๐.๐๐พ๐๐ฝ('๐๐พ๐
๐
๐'); // ๐ฑ๐๐๐๐๐๐พ ๐พ๐๐๐๐
`
๐๐จ๐จ๐:
`๐๐๐๐พ๐๐ผ๐๐๐๐
๐๐๐๐พ ๐ฃ๐๐๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ = { ๐๐พ๐บ๐ฝ๐๐๐
๐ ๐๐๐บ๐๐พ: '๐ฝ๐๐๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ' };
๐๐๐๐พ ๐ข๐๐๐๐พ๐ผ๐๐พ๐ฝ = { ๐๐พ๐บ๐ฝ๐๐๐
๐ ๐๐๐บ๐๐พ: '๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ' };
๐ผ๐
๐บ๐๐ ๐ข๐๐๐๐พ๐ผ๐๐๐๐<๐ฒ๐๐บ๐๐พ> {
๐๐๐๐๐บ๐๐พ ๐ผ๐๐๐๐๐๐๐ผ๐๐๐(๐๐๐๐๐บ๐๐พ ๐๐๐บ๐๐พ: ๐ฒ๐๐บ๐๐พ) {}
๐๐๐บ๐๐๐ผ ๐ผ๐๐พ๐บ๐๐พ(): ๐ข๐๐๐๐พ๐ผ๐๐๐๐<๐ฃ๐๐๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ> {
๐๐พ๐๐๐๐ ๐๐พ๐ ๐ข๐๐๐๐พ๐ผ๐๐๐๐({ ๐๐๐บ๐๐พ: '๐ฝ๐๐๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ' });
}
๐ผ๐๐๐๐พ๐ผ๐(๐๐๐๐: ๐ข๐๐๐๐พ๐ผ๐๐๐๐<๐ฃ๐๐๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ>): ๐ข๐๐๐๐พ๐ผ๐๐๐๐<๐ข๐๐๐๐พ๐ผ๐๐พ๐ฝ> {
๐๐พ๐๐๐๐ ๐๐พ๐ ๐ข๐๐๐๐พ๐ผ๐๐๐๐({ ๐๐๐บ๐๐พ: '๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ' });
}
๐๐พ๐๐ฝ(๐๐๐๐: ๐ข๐๐๐๐พ๐ผ๐๐๐๐<๐ข๐๐๐๐พ๐ผ๐๐พ๐ฝ>, ๐ฝ๐บ๐๐บ: ๐๐๐๐๐๐) {
// ๐ข๐บ๐ ๐๐๐
๐ ๐ผ๐บ๐
๐
๐๐ฟ ๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ
}
}
๐ผ๐๐๐๐ ๐ผ๐๐๐ = ๐ข๐๐๐๐พ๐ผ๐๐๐๐.๐ผ๐๐พ๐บ๐๐พ();
๐ผ๐๐๐.๐๐พ๐๐ฝ('๐๐พ๐
๐
๐'); // ๐ณ๐๐๐พ ๐พ๐๐๐๐: ๐๐๐ ๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ
๐ผ๐๐๐๐ ๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ = ๐ผ๐๐๐.๐ผ๐๐๐๐พ๐ผ๐();
๐ผ๐๐๐๐พ๐ผ๐๐พ๐ฝ.๐๐พ๐๐ฝ('๐๐พ๐
๐
๐'); // ๐ฎ๐ช
`
Illegal states become unrepresentable.
---
The mindset shift:
Rust: Make invalid states impossible to represent
TypeScript default: Let anything happen, hope for the best
TypeScript with discipline: Make invalid states impossible to represent
---
You don't need Rust to write correct code.
You need Rust's mindset applied to whatever language you're using.
Make errors explicit. Make invalid states unrepresentable. Make the compiler your ally.
That's type safety. Not just slapping `: string` on everything.