TypeScript: Tipos utilitários do TypeScript

Última atualização: 2026-08-26

O TypeScript inclui mais de uma dúzia de tipos utilitários — eles representam as melhores práticas em programação genérica e permitem realizar conversões de tipos comuns com uma única linha de código.

1. Classe de transformação de propriedades

(1) Parcial — Todas as propriedades passam a ser opcionais

TYPESCRIPT
interface User {
  id: number;
  name: string;
  email: string;
  age: number;
}

// Partial Make all properties optional——Suitable for update operations
type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; age?: number }

function updateUser(user: User, updates: Partial<User>): User {
  return { ...user, ...updates };
}

let user: User = { id: 1, name: "Charlie", email: "xiao@example.com", age: 20 };
let updated = updateUser(user, { age: 21 });
// Update Only age,All other attributes remain unchanged

console.log(updated.age);   // 21
console.log(updated.name);  // "Charlie"(Unchanged)

(2) Obrigatório — Agora, todas as propriedades são obrigatórias

TYPESCRIPT
interface Config {
  host?: string;
  port?: number;
  debug?: boolean;
}

// Required Make all fields required——Suitable for verifying logic
type RequiredConfig = Required<Config>;
// { host: string; port: number; debug: boolean }

function validateConfig(config: RequiredConfig): void {
  console.log(`${config.host}:${config.port} (debug: ${config.debug})`);
}

(3) Somente leitura — Todas as propriedades passam a ser somente leitura

TYPESCRIPT
interface Point {
  x: number;
  y: number;
}

// Readonly Make all properties read-only
type ReadonlyPoint = Readonly<Point>;
// { readonly x: number; readonly y: number }

let point: ReadonlyPoint = { x: 1, y: 2 };
// point.x = 10;  // ❌ Read-only properties cannot be modified.

// Common Uses:Function Parameter Protection
function freezeConfig(config: Readonly<Config>): void {
  // config.host = "other";  // ❌ Modifications are not allowed.
  console.log("Configuration Frozen");
}

▶ Exemplo: Conversão de tipos em CRUD

TYPESCRIPT
interface Article {
  id: number;
  title: string;
  content: string;
  author: string;
  createdAt: Date;
  updatedAt: Date;
}

// At the time of creation:Not necessary id and timestamps
type CreateArticle = Omit<Article, "id" | "createdAt" | "updatedAt">;

// When updating:All fields are optional
type UpdateArticle = Partial<Omit<Article, "id" | "createdAt">>;

// List View:Show only some fields
type ArticleSummary = Pick<Article, "id" | "title" | "author" | "createdAt">;

// Create
let newArticle: CreateArticle = {
  title: "TypeScriptGetting Started",
  content: "TypeScript is a superset of JavaScript...",
  author: "Charlie"
};

// Update
let updateData: UpdateArticle = {
  title: "TypeScript Advanced",
  content: "An In-Depth Understanding of Generics..."
};

// List
let summary: ArticleSummary = {
  id: 1,
  title: "TypeScriptGetting Started",
  author: "Charlie",
  createdAt: new Date()
};

console.log("Create:" + newArticle.title);
console.log("Update:" + (updateData.title ?? "No changes"));
console.log("Abstract:" + summary.title);
▶ Experimente

Saída:

TEXT 📖 Somente leitura
Create:TypeScriptGetting Started
Update:TypeScript Advanced
Abstract:TypeScriptGetting Started


2. Aula sobre seleção de atributos

(1) Escolha — Selecione determinados atributos

TYPESCRIPT
interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  role: string;
}

// Pick Select the specified property
type UserPublic = Pick<User, "id" | "name" | "email">;
// { id: number; name: string; email: string }

let publicProfile: UserPublic = {
  id: 1,
  name: "Charlie",
  email: "xiao@example.com"
};
// None password and role —— Safely Disclosing Public Information

(2) Omitir — Excluir determinados atributos

TYPESCRIPT
// Omit Exclude the specified properties(Pick the opposite of)
type UserSafe = Omit<User, "password">;
// { id: number; name: string; email: string; role: string }

let safeUser: UserSafe = {
  id: 1,
  name: "Charlie",
  email: "xiao@example.com",
  role: "admin"
};
// password Excluded

(3) Escolher ou omitir: a escolha

TYPESCRIPT
// Retain a few properties → Pick More concise
type Mini = Pick<User, "id" | "name">;           // 2a property → Pick

// Exclude a few attributes → Omit More concise
type NoPassword = Omit<User, "password">;         // Exclusion1 → Omit

// Preserve Most Properties → Omit More concise
type AlmostAll = Omit<User, "password">;          // Retain4 → Omit

// Exclude Most Attributes → Pick More concise
type OnlyTwo = Pick<User, "id" | "name">;         // Exclusion3 → Pick


3. Classes de operação do tipo união

(1) Excluir — Excluir do tipo de união

TYPESCRIPT
type AllTypes = "a" | "b" | "c" | "d";

// Exclude Exclude Specified Members
type WithoutA = Exclude<AllTypes, "a">;        // "b" | "c" | "d"
type WithoutAB = Exclude<AllTypes, "a" | "b">; // "c" | "d"

(2) Extração — Extração de um tipo de união

TYPESCRIPT
type Mixed = string | number | boolean | null;

// Extract Extract Specified Members
type OnlyString = Extract<Mixed, string>;       // string
type StringOrNumber = Extract<Mixed, string | number>;  // string | number

(3) NonNullable — Excluir valores nulos e indefinidos

TYPESCRIPT
type MaybeString = string | null | undefined;

// NonNullable Exclusion null and undefined
type DefiniteString = NonNullable<MaybeString>;  // string

▶ Exemplo: Filtragem de valores inválidos

TYPESCRIPT
type EventName = "click" | "focus" | "blur" | null | undefined;

// Exclusion null and undefined
type ValidEvent = NonNullable<EventName>;  // "click" | "focus" | "blur"

// Keep only mouse events
type MouseEvent = Extract<ValidEvent, "click">;  // "click"

// Exclusion click Unforeseen events
type NonClick = Exclude<ValidEvent, "click">;    // "focus" | "blur"

function handleEvent(event: ValidEvent): void {
  console.log(`Handling Events:${event}`);
}

handleEvent("click");   // ✅
handleEvent("focus");   // ✅
// handleEvent(null);   // ❌ NonNullable Ruled out
▶ Experimente

Saída:

TEXT 📖 Somente leitura
// Executed successfully


4. Classes de operação do tipo função

(1) ReturnType — Obter o tipo de retorno da função

TYPESCRIPT
function createUser(name: string, age: number) {
  return { name, age, active: true };
}

// ReturnType Get the return type——No handwriting required
type User = ReturnType<typeof createUser>;
// { name: string; age: number; active: boolean }

let user: User = { name: "Diana", age: 22, active: false };

(2) Parâmetros — Recuperar uma tupla com os tipos dos parâmetros da função

TYPESCRIPT
function register(name: string, email: string, age: number): void {}

// Parameters Get Parameter Type
type RegisterParams = Parameters<typeof register>;
// [string, string, number]

let params: RegisterParams = ["Charlie", "xiao@example.com", 20];

(3) ConstructorParameters — Obter os tipos dos parâmetros do construtor

TYPESCRIPT
class Point {
  constructor(public x: number, public y: number, public z?: number) {}
}

type PointParams = ConstructorParameters<typeof Point>;
// [number, number, number?]

let args: PointParams = [1, 2];
let point = new Point(...args);

(4) InstanceType — Obter o tipo da instância do construtor

TYPESCRIPT
class Session {
  constructor(public token: string) {}
  isValid(): boolean { return this.token.length > 0; }
}

type SessionInstance = InstanceType<typeof Session>;
// Equivalent to Session Type

let session: SessionInstance = new Session("abc123");


5. Record — Criando um tipo de par chave-valor

Record é um dos tipos de dados mais utilizados — um tipo que permite criar rapidamente mapeamentos do tipo “chave-valor”:

TYPESCRIPT
// Basic Usage:Key and Value Types
type StringMap = Record<string, string>;
let translations: StringMap = {
  hello: "Hello",
  goodbye: "Goodbye"
};

// Coordinated Literal-Union Types——Precision Control Key
type Theme = "light" | "dark";
type ThemeColors = Record<Theme, { bg: string; text: string }>;

let themes: ThemeColors = {
  light: { bg: "#ffffff", text: "#333333" },
  dark: { bg: "#1a1a1a", text: "#e0e0e0" }
};

// Abbreviation: Use Record instead of handwritten Object Types
type Scores = Record<"Chinese Language" | "Mathematics" | "English", number>;
let myScores: Scores = { Chinese Language: 90, Mathematics: 95, English: 88 };


6. Como funcionam os tipos de ferramentas

Compreender a implementação subjacente dos tipos de ferramentas ajuda a personalizá-los:

(1) Implementação de Partial

TYPESCRIPT
type Partial<T> = {
  [K in keyof T]?: T[K];
};

(2) Implementação do Readonly

TYPESCRIPT
type Readonly<T> = {
  readonly [K in keyof T]: T[K];
};

(3) Implementação do Pick

TYPESCRIPT
type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

(4) Implementação do Omit

TYPESCRIPT
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

(5) Implementação do Record

TYPESCRIPT
type Record<K extends keyof any, T> = {
  [P in K]: T;
};

▶ Exemplo: Tipos de ferramentas personalizadas

TYPESCRIPT
// DeepPartial——Recursion makes all levels optional
type DeepPartial<T> = {
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};

interface Config {
  server: {
    host: string;
    port: number;
  };
  database: {
    url: string;
    pool: {
      min: number;
      max: number;
    };
  };
}

type PartialConfig = DeepPartial<Config>;
// Properties at all levels are now optional

let config: PartialConfig = {
  server: { host: "localhost" }  // port Can be omitted
  // database The entire section can be omitted.
};

// DeepReadonly——Recursively set all levels to read-only
type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};

type FrozenConfig = DeepReadonly<Config>;
// config.server.host = "other";  // ❌ Deep Read-Only
▶ Experimente

Saída:

TEXT 📖 Somente leitura
// Executed successfully

❓ Perguntas Frequentes

P: Qual é a diferença entre Partial e propriedades opcionais? R: As propriedades opcionais são marcadas manualmente com ? when defining an interface. Partial is a tool type—it automatically makes all properties of an existing type optional. The difference is that Partial is "derived from an existing type" and does not require redefining the interface. In actual development, the UpdateUser = Partial&lt;User&gt;. A operação de atualização é o caso de uso mais comum.

P: Devo usar Pick ou Omit? R: Depende do que for mais conciso — use Pick quando houver menos propriedades a serem mantidas e use Omit quando houver menos propriedades a serem excluídas. Os dois são complementares; escolha o mais curto. A legibilidade do código é fundamental — Omit<User, "password"> é muito mais claro do que Pick<User, "id" | "name" | "email" | "role">.

P: O ReturnType consegue determinar o tipo de retorno de uma função assíncrona? R: As funções assíncronas retornam uma Promise; o ReturnType<typeof asyncFn> retorna Promise<T> em vez de T. É preciso desembrulhar a Promise usando Awaited<ReturnType<typeof asyncFn>> (o TypeScript 4.5+ inclui o tipo Awaited).

P: O tipo de ferramenta afeta o desempenho? R: Não. O tipo de ferramenta é puramente uma construção em tempo de compilação — todas as informações de tipo são apagadas após a compilação, resultando em sobrecarga zero em tempo de execução. No entanto, um aninhamento excessivamente complexo de tipos pode aumentar o tempo de compilação, embora o impacto real seja insignificante.

📖 Resumo

📝 Exercícios

  1. Exercício básico (Dificuldade ⭐): Defina a interface Todo (id, título, concluído, criadoEm), e depois use o tipo de ferramenta para criar: CreateTodo (id e hora não são obrigatórios na criação), UpdateTodo (todos os campos são opcionais na atualização) e TodoPreview (exibe apenas título e concluído).
  2. Exercício avançado (Dificuldade ⭐⭐): Personalize o tipo de ferramenta Mutable<T> — remova todos os modificadores readonly (usando o mapeamento de modificadores -readonly). Em seguida, use Readonly<Config> para criar uma configuração somente leitura e use Mutable<Readonly<Config>> para verificar se a capacidade de gravação foi restaurada.
  3. Desafio (Dificuldade: ⭐⭐⭐): Implemente o tipo de ferramenta PathKeys<T> — extraia recursivamente todos os caminhos das propriedades de objetos aninhados. Por exemplo, { user: { name: string; address: { city: string } } }"user" | "user.name" | "user.address" | "user.address.city".
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%