Replace Elysia with bun.serve for hot reloading and static serving

This commit is contained in:
2025-10-22 19:56:38 -07:00
parent b136c6e63a
commit cd88f570a0
13 changed files with 522 additions and 27 deletions

View File

@@ -0,0 +1,108 @@
---
title: 5 TypeScript Tips I Wish I Knew Earlier
date: 2025-09-18
tags: [TypeScript, JavaScript, Productivity]
excerpt: Five practical TypeScript tips that will make your code more type-safe and your development experience smoother. From utility types to const assertions.
draft: false
---
# 5 TypeScript Tips I Wish I Knew Earlier
TypeScript is an amazing tool, but it takes time to learn all its features. Here are five tips that significantly improved my TypeScript development.
## 1. Use `satisfies` for Type Checking
The `satisfies` keyword (added in TS 4.9) lets you validate that a value matches a type without widening its type:
```typescript
type RGB = { r: number; g: number; b: number };
// Before: Type is widened to RGB
const color: RGB = { r: 255, g: 0, b: 0 };
// After: Type is preserved as literal values
const color = { r: 255, g: 0, b: 0 } satisfies RGB;
```
This is especially useful when you want both type safety and precise types.
## 2. Const Assertions
Adding `as const` to an object or array makes all properties readonly and infers literal types:
```typescript
// Regular array: type is string[]
const fruits = ['apple', 'banana'];
// With const assertion: type is readonly ['apple', 'banana']
const fruits = ['apple', 'banana'] as const;
```
This is perfect for configuration objects and enum-like values.
## 3. Utility Type: `Awaited<T>`
Need to get the resolved type of a Promise? Use `Awaited`:
```typescript
async function fetchUser() {
return { id: 1, name: 'Alice' };
}
// Gets the return type without the Promise wrapper
type User = Awaited<ReturnType<typeof fetchUser>>;
// User is { id: number; name: string }
```
## 4. Template Literal Types
Create types based on string patterns:
```typescript
type EventName = 'click' | 'focus' | 'blur';
type EventHandler = `on${Capitalize<EventName>}`;
// Result: 'onClick' | 'onFocus' | 'onBlur'
```
This is incredibly powerful for creating type-safe APIs.
## 5. Discriminated Unions
Use a common property to narrow union types:
```typescript
type Success = { status: 'success'; data: string };
type Error = { status: 'error'; error: string };
type Result = Success | Error;
function handle(result: Result) {
if (result.status === 'success') {
// TypeScript knows this is Success
console.log(result.data);
} else {
// TypeScript knows this is Error
console.log(result.error);
}
}
```
This pattern eliminates entire classes of runtime errors.
## Bonus: Non-Null Assertion Operator
While I generally avoid the `!` operator, it's useful when you know better than TypeScript:
```typescript
// When you're certain the element exists
const button = document.getElementById('submit')!;
button.click();
```
Use sparingly and only when you're absolutely sure.
## Wrapping Up
These tips have made my TypeScript code more robust and easier to maintain. The key is to leverage TypeScript's type system to catch errors at compile time rather than runtime.
What are your favorite TypeScript features? Let me know!