5 Tipos Utilitários do TypeScript Que Você Deveria Conhecer

O sistema de tipos do TypeScript se torna verdadeiramente poderoso quando você descobre os tipos utilitários—auxiliares integrados que transformam tipos existentes sem reescrevê-los. Se você já se viu duplicando interfaces ou lutando com modificações de tipos, estes cinco tipos utilitários essenciais vão mudar como você escreve código TypeScript.
Pontos-Chave
- Tipos utilitários transformam tipos existentes sem reescrevê-los, reduzindo duplicação de código
- Partial torna todas as propriedades opcionais, perfeito para operações de atualização
- Required força todas as propriedades, garantindo estruturas de dados completas
- Pick e Omit ajudam a criar interfaces focalizadas selecionando ou excluindo propriedades
- Readonly previne mutações acidentais, essencial para padrões de dados imutáveis
O Que São Tipos Utilitários do TypeScript e Por Que Importam
Tipos utilitários são tipos genéricos pré-construídos do TypeScript que constroem novos tipos transformando os existentes. Em vez de criar manualmente variações das suas interfaces, estes utilitários permitem derivar novos tipos com modificações específicas—tornando seu código mais manutenível e reduzindo duplicação de tipos.
Vamos explorar cinco tipos utilitários fundamentais que resolvem problemas comuns do mundo real: Partial, Required, Pick, Omit e Readonly. Cada um aborda cenários específicos que você encontra diariamente no desenvolvimento TypeScript.
Partial<T>: Tornando Todas as Propriedades Opcionais no TypeScript
O tipo utilitário Partial transforma todas as propriedades de um tipo em opcionais, perfeito para operações de atualização onde você modifica apenas campos específicos.
Quando Usar Partial para Atualizações de Formulário
Considere uma atualização de perfil de usuário onde os usuários podem alterar campos individuais sem enviar o objeto inteiro:
interface User {
id: string;
name: string;
email: string;
avatar: string;
lastLogin: Date;
}
function updateUserProfile(userId: string, updates: Partial<User>) {
// Atualiza apenas os campos fornecidos
return api.patch(`/users/${userId}`, updates);
}
// Uso - atualizando apenas o email
updateUserProfile("123", { email: "new@email.com" });
Exemplo de Tipo Partial com Código do Mundo Real
Atualizações de estado do React se beneficiam significativamente do Partial:
const [user, setUser] = useState<User>(initialUser);
const updateUser = (updates: Partial<User>) => {
setUser(prev => ({ ...prev, ...updates }));
};
// Atualiza apenas campos específicos
updateUser({ name: "Jane Doe", avatar: "new-avatar.jpg" });
Required<T>: Forçando Todas as Propriedades no TypeScript
Required faz o oposto do Partial—torna todas as propriedades opcionais obrigatórias, garantindo estruturas de dados completas.
Convertendo Propriedades Opcionais em Obrigatórias
Isso se mostra inestimável para validação de configuração:
interface DatabaseConfig {
host?: string;
port?: number;
username?: string;
password?: string;
}
// Garante que todos os valores de configuração existam antes de conectar
type ValidatedConfig = Required<DatabaseConfig>;
function connectDatabase(config: ValidatedConfig) {
// Todas as propriedades garantidamente existem
return createConnection(config);
}
Tipo Required em Ação
Submissão de formulários frequentemente requer dados completos:
interface RegistrationForm {
username?: string;
email?: string;
password?: string;
terms?: boolean;
}
type CompleteRegistration = Required<RegistrationForm>;
function submitRegistration(data: CompleteRegistration) {
// Todos os campos devem estar preenchidos
api.post('/register', data);
}
Discover how at OpenReplay.com.
Pick<T, K>: Selecionando Propriedades Específicas de Tipos
Pick cria um novo tipo selecionando apenas propriedades especificadas, ideal para criar interfaces focalizadas.
Criando Subconjuntos de Tipos Focalizados com Pick
Extraia apenas o que você precisa para componentes específicos:
interface Article {
id: string;
title: string;
content: string;
author: string;
publishedAt: Date;
tags: string[];
}
// Componente de card precisa apenas destes campos
type ArticlePreview = Pick<Article, 'id' | 'title' | 'author'>;
function ArticleCard({ article }: { article: ArticlePreview }) {
return (
<div>
<h3>{article.title}</h3>
<p>por {article.author}</p>
</div>
);
}
Pick vs Omit: Escolhendo a Abordagem Certa
Use Pick quando precisar de poucas propriedades, Omit quando excluir poucas propriedades:
// Pick: Quando você precisa de 2-3 propriedades de um tipo grande
type UserSummary = Pick<User, 'id' | 'name'>;
// Omit: Quando você precisa da maioria das propriedades exceto algumas
type PublicUser = Omit<User, 'password'>;
Omit<T, K>: Excluindo Propriedades de Tipos TypeScript
Omit cria um tipo excluindo propriedades especificadas, perfeito para remover campos sensíveis ou internos.
Removendo Dados Sensíveis com Omit
Proteja informações sensíveis em respostas de API:
interface UserAccount {
id: string;
email: string;
password: string;
creditCard: string;
publicProfile: boolean;
}
// Remove campos sensíveis para API pública
type PublicUserData = Omit<UserAccount, 'password' | 'creditCard'>;
function getPublicProfile(userId: string): Promise<PublicUserData> {
return api.get(`/users/${userId}/public`);
}
Melhores Práticas do Tipo Utilitário Omit
Combine com outros utilitários para padrões poderosos:
// Remove campos internos e torna os restantes opcionais
type UserUpdatePayload = Partial<Omit<User, 'id' | 'createdAt'>>;
Readonly<T>: Criando Tipos Imutáveis no TypeScript
Readonly torna todas as propriedades imutáveis, prevenindo mutações acidentais e garantindo integridade dos dados.
Prevenindo Mutações Acidentais com Readonly
Essencial para gerenciamento de estado e configuração:
interface AppConfig {
apiEndpoint: string;
version: string;
features: string[];
}
type ImmutableConfig = Readonly<AppConfig>;
const config: ImmutableConfig = {
apiEndpoint: "https://api.example.com",
version: "1.0.0",
features: ["auth", "payments"]
};
// Erro do TypeScript: Cannot assign to 'apiEndpoint' because it is a read-only property
config.apiEndpoint = "https://new-api.com"; // ❌
Propriedades Readonly e Props do React
Garanta que props permaneçam inalteradas:
type UserCardProps = Readonly<{
user: User;
onSelect: (id: string) => void;
}>;
function UserCard({ user, onSelect }: UserCardProps) {
// Props são imutáveis dentro do componente
return <div onClick={() => onSelect(user.id)}>{user.name}</div>;
}
Combinando Múltiplos Tipos Utilitários para Padrões Avançados
Tipos utilitários se tornam ainda mais poderosos quando combinados:
interface DatabaseRecord {
id: string;
createdAt: Date;
updatedAt: Date;
deletedAt?: Date;
data: Record<string, unknown>;
}
// Cria um tipo para novos registros: sem timestamps, dados parciais
type NewRecord = Omit<DatabaseRecord, 'id' | 'createdAt' | 'updatedAt'> & {
data: Partial<DatabaseRecord['data']>;
};
// Tipo de atualização: tudo opcional exceto ID
type UpdateRecord = Partial<Omit<DatabaseRecord, 'id'>> & Pick<DatabaseRecord, 'id'>;
Conclusão
Estes cinco tipos utilitários—Partial, Required, Pick, Omit e Readonly—formam a base do desenvolvimento eficaz em TypeScript. Eles eliminam definições repetitivas de tipos, garantem segurança de tipos e tornam seu código mais manutenível.
Comece incorporando estes padrões na sua base de código. Inicie com Partial para operações de atualização, use Omit para criar interfaces públicas seguras e aproveite Readonly para prevenir bugs. À medida que se torna confortável, combine-os para criar transformações sofisticadas de tipos que correspondem perfeitamente às necessidades da sua aplicação.
Perguntas Frequentes
Sim, você pode aninhar tipos utilitários para criar transformações complexas. Por exemplo, Partial e Omit funcionam bem juntos para criar payloads de atualização que excluem certos campos enquanto tornam outros opcionais.
Não, tipos utilitários são construções puramente de tempo de compilação. O TypeScript remove todas as informações de tipo durante a compilação, então tipos utilitários têm zero overhead em runtime.
Extensão de interface cria novos tipos adicionando propriedades, enquanto tipos utilitários transformam tipos existentes. Tipos utilitários oferecem mais flexibilidade para modificar tipos que você não controla ou criar variações de tipos existentes.
Sim, o TypeScript permite criar tipos utilitários personalizados usando mapped types, conditional types e template literal types. Comece com utilitários integrados e crie personalizados quando identificar padrões repetidos.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.