
1. Branded Types para IDs
Nunca mais confunda um userId com um postId:
type Brand<T, B> = T & { __brand: B };
type UserId = Brand<string, "UserId">;
type PostId = Brand<string, "PostId">;
function getUser(id: UserId) { /* ... */ }
const userId = "abc" as UserId;
const postId = "xyz" as PostId;
getUser(userId); // OK
getUser(postId); // Erro de tipo!
2. Template Literal Types
Crie tipos a partir de strings:
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type ApiRoute = `/api/${string}`;
type Endpoint = `${HttpMethod} ${ApiRoute}`;
// "GET /api/users" ✓
// "PATCH /api/users" ✗
3. satisfies para o melhor dos dois mundos
Valide o tipo sem perder a inferência:
const config = {
port: 3000,
host: "localhost",
debug: true,
} satisfies Record<string, string | number | boolean>;
// config.port ainda é `number`, não `string | number | boolean`
4. Tipos Condicionais Recursivos
type DeepReadonly<T> = T extends object
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T;
5. infer para extrair tipos
type ReturnTypeOf<T> = T extends (...args: never[]) => infer R ? R : never;
type PromiseValue<T> = T extends Promise<infer V> ? V : T;
Dominar esses padrões separa um dev TypeScript bom de um excelente.


