Arquitetura de Software
Utility Types
Partial, Pick, Omit, Record, Extract, Exclude, ReturnType, Parameters — tipos utilitários embutidos e customizados.
1 min de leitura
Utility Types em TypeScript
TypeScript vem com um conjunto de tipos utilitários (utility types) que transformam tipos existentes. São como funções, mas para tipos.
Tipos utilitários embutidos
Partial<T> — Torna todas as propriedades opcionais
interface User {
id: string;
name: string;
email: string;
age: number;
}
type PartialUser = Partial<User>;
// { id?: string; name?: string; email?: string; age?: number; }
// Uso: updates parciais
function updateUser(id: string, data: Partial<User>): Promise<User> {
// só precisa passar os campos que quer alterar
return db.users.update(id, data);
}
updateUser('1', { name: 'Novo Nome' }); // ✅ só altera o nomeRequired<T> — Torna todas as propriedades obrigatórias
type Config = {
host?: string;
port?: number;
database?: string;
};
type RequiredConfig = Required<Config>;
// { host: string; port: number; database: string; }
// Uso: garantir que configuração está completa
function startServer(config: Required<Config>) {
// TS garante que host, port e database existem
}Pick<T, K> — Seleciona propriedades específicas
type UserPublic = Pick<User, 'id' | 'name'>;
// { id: string; name: string; }
// Uso: DTOs públicos que expõem menos dados
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
const publicData: Pick<User, 'id' | 'name' | 'email'> = {
id: user.id,
name: user.name,
email: user.email,
};
res.json(publicData);
});Omit<T, K> — Remove propriedades específicas
type CreateUserDto = Omit<User, 'id'>;
// { name: string; email: string; age: number; }
// id é removido — o banco gera
// Uso: criar sem ID
async function createUser(data: CreateUserDto): Promise<User> {
const id = generateId();
return db.users.create({ id, ...data });
}Record<K, V> — Cria tipo de objeto com chaves e valores fixos
type StatusMap = Record<string, string>;
// { [key: string]: string }
// Mais específico
type HttpCodes = Record<'ok' | 'created' | 'notFound' | 'error', number>;
const codes: HttpCodes = {
ok: 200,
created: 201,
notFound: 404,
error: 500,
};
// Frontend — configuração de rotas
type RouteConfig = Record<string, { path: string; component: React.ComponentType }>;Extract<T, U> e Exclude<T, U> — Filtra union types
type AllStatus = 'active' | 'inactive' | 'pending' | 'deleted' | 'banned';
type ActiveStatuses = Extract<AllStatus, 'active' | 'pending'>;
// 'active' | 'pending'
type NonDeletedStatuses = Exclude<AllStatus, 'deleted' | 'banned'>;
// 'active' | 'inactive' | 'pending'ReturnType<T> e Parameters<T> — Deriva de funções
function getUser(id: string): { name: string; email: string } {
return db.users.findById(id);
}
type UserReturn = ReturnType<getUser>;
// { name: string; email: string }
type UserParams = Parameters<getUser>;
// [id: string]
// Uso: manter tipos sincronizados automaticamente
type FetchResult = ReturnType<typeof fetchUser>;
// Se fetchUser mudar o retorno, FetchResult atualiza sozinhoAwaited<T> — Extrai o tipo de uma Promise
type UserPromise = Promise<User>;
type UserResolved = Awaited<UserPromise>;
// User
// Útil para tipar o resultado de operações async sem duplicar
async function loadDashboard() {
const user = await fetchUser(); // User
const orders = await fetchOrders(); // Order[]
const stats = await fetchStats(); // Stats
return { user, orders, stats };
}
type DashboardData = Awaited<ReturnType<typeof loadDashboard>>;
// { user: User; orders: Order[]; stats: Stats }Utility types customizados
Nullable<T> — Adiciona null e undefined
type Nullable<T> = T | null | undefined;
function findUser(id: string): Nullable<User> {
return db.users.findById(id) ?? undefined;
}DeepPartial<T> — Partial recursivo
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
interface Config {
server: {
host: string;
port: number;
ssl: {
enabled: boolean;
cert: string;
};
};
db: {
url: string;
poolSize: number;
};
}
type PartialConfig = DeepPartial<Config>;
// server.ssl.enabled pode ser definido sem definir server.host
const override: PartialConfig = {
server: { ssl: { enabled: true } }, // ✅ TS aceita — não precisa definir host nem port
};NonNullableProperties<T> — Remove null de todas as propriedades
type NonNullableProperties<T> = {
[K in keyof T]: NonNullable<T[K]>;
};
interface FormState {
name: string | null;
email: string | null;
age: number | null;
}
type ValidatedForm = NonNullableProperties<FormState>;
// { name: string; email: string; age: number; }
function validateForm(form: FormState): ValidatedForm {
if (!form.name || !form.email || !form.age) {
throw new Error('Todos os campos são obrigatórios');
}
return form as ValidatedForm; // ✅ TS sabe que nada é null
}