Menu

Perguntas de entrevista de TypeScript e respostas (25 com código)

25 perguntas de entrevista de TypeScript com respostas curtas e corretas e código, agrupadas do nível iniciante ao avançado: any vs unknown, interface vs type, generics, narrowing, utility types, mapped e conditional types, tipagem estrutural, tsconfig e TypeScript 7.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Estas são as perguntas de TypeScript que os entrevistadores mais fazem, com a resposta curta que você deve saber dar e um pequeno exemplo. Elas estão agrupadas por nível; uma vaga júnior geralmente para no primeiro grupo, e uma sênior espera que você escreva de memória os tipos do último grupo.

Perguntas para iniciantes

1. O que é TypeScript?

TypeScript é JavaScript com tipos estáticos, criado pela Microsoft. Você anota os valores com tipos, o compilador os verifica e depois remove os tipos e gera JavaScript puro, que roda em qualquer lugar onde JavaScript roda.

Sem o comentário @ts-expect-error, a segunda chamada é um erro de compilação, então o bug nunca chega à produção.

2. O TypeScript verifica tipos em tempo de execução?

Não. Os tipos são apagados durante a compilação; a saída não tem nenhum vestígio deles. A execução acima imprime 23 porque nada em tempo de execução sabe que a deveria ser um número. Para verificar dados de fora do programa (JSON, entrada do usuário, respostas de API), você escreve verificações reais, como um type guard ou um validador de schema.

3. Quais são os tipos básicos?

string, number (um único tipo para inteiros e decimais; não existe int), boolean, bigint, symbol, null e undefined, mais arrays (number[]), tuplas ([string, number]), tipos de objeto, any, unknown, never e void. Use os nomes minúsculos: String e Number são os tipos dos objetos wrapper.

4. Qual é a diferença entre any e unknown?

Os dois aceitam qualquer valor. any também desliga a verificação, então qualquer operação compila. unknown não permite nada até você estreitá-lo, o que faz dele o tipo seguro para valores que você ainda não verificou.

5. O que é inferência de tipos?

O compilador deduz os tipos que você não escreveu: let count = 0 é um number, const mode = "dark" é o tipo literal "dark", e o tipo de retorno de uma função vem das suas instruções return. A regra usual é anotar os parâmetros das funções e os tipos de retorno públicos e deixar a inferência cuidar das variáveis locais.

6. Qual é a diferença entre interface e type?

Os dois descrevem formatos de objeto, e uma classe pode fazer implements de qualquer um. Uma interface pode ser reaberta e mesclada (declaration merging) e pode fazer extends de outras interfaces. Um type alias com type pode dar nome a qualquer coisa: unions, tuplas, primitivos, mapped e conditional types.

interface User { name: string }
interface User { age: number }       // merged: User has name and age

type Id = string | number;           // only a type alias can be a union
type Pair = [string, number];        // or a tuple
type Admin = User & { role: "admin" };

Uma convenção comum é interface para formatos de objeto e type para todo o resto. A comparação completa está na página interface vs type.

7. O que são union types e intersection types?

Uma union A | B é um valor que é um dos tipos; você só pode usar os membros comuns a todos eles até estreitá-lo. Uma intersection A & B é um valor que é os dois ao mesmo tempo, com todos os membros de cada um.

type Id = string | number;                 // either
type Timestamped = { createdAt: Date };
type Post = { title: string } & Timestamped; // both: title and createdAt

8. Qual é a diferença entre void e never?

void é o tipo de retorno de uma função que retorna normalmente, sem um valor útil. never é o tipo de algo que não pode acontecer: uma função que sempre lança exceção ou fica em loop para sempre, ou uma union da qual todos os casos foram removidos. never pode ser atribuído a qualquer tipo, e nenhum valor pode ser atribuído a never.

function log(msg: string): void { console.log(msg); }
function fail(msg: string): never { throw new Error(msg); }
type Impossible = string & number; // never

Perguntas de nível intermediário

9. O que é type narrowing?

Narrowing é o compilador acompanhando as suas verificações e refinando um tipo dentro de cada ramo. Ele entende typeof, instanceof, in, comparações de igualdade, truthiness e type guards definidos pelo usuário.

10. O que é um type guard definido pelo usuário?

Uma função cujo tipo de retorno é value is T. Quando ela retorna true, a variável de quem chama é estreitada para T. O compilador confia na função, então o corpo dela precisa verificar o valor de verdade.

interface Cat { meow(): void }

function isCat(value: unknown): value is Cat {
    return (
        typeof value === "object" &&
        value !== null &&
        "meow" in value &&
        typeof value.meow === "function"
    );
}

Uma assertion function, function assertCat(v: unknown): asserts v is Cat, estreita lançando um erro em vez de retornar false.

11. O que são generics?

Parâmetros de tipo que permitem que uma função, classe ou tipo funcione com vários tipos mantendo a ligação entre entrada e saída. T é inferido a partir dos argumentos, e extends restringe o que ele pode ser.

pluck(users, "email") seria um erro de compilação, porque "email" não é um keyof do tipo de usuário.

12. O que keyof e typeof fazem em um tipo?

keyof T é a union dos nomes das propriedades de T. Em posição de tipo, typeof x dá o tipo de uma variável. Juntos, keyof typeof obj transformam as chaves de um objeto em uma union.

const colors = { red: "#f00", green: "#0f0" };
type Colors = typeof colors;        // { red: string; green: string }
type ColorName = keyof typeof colors; // "red" | "green"

13. O que são utility types? Cite alguns.

Tipos genéricos nativos que transformam outros tipos. Os mais perguntados:

UtilityResultado
Partial<T>todas as propriedades opcionais
Required<T>todas as propriedades obrigatórias
Readonly<T>todas as propriedades readonly
Pick<T, "a" | "b">só as propriedades listadas
Omit<T, "a">todas as propriedades, exceto as listadas
Record<K, V>um objeto com chaves K e valores V
Exclude<U, X>, Extract<U, X>remove ou mantém membros de uma union
NonNullable<T>T sem null e undefined
ReturnType<F>, Parameters<F>os tipos de retorno ou de parâmetros de uma função
Awaited<T>o valor com que uma promise é resolvida

A lista completa está na página de utility types.

14. O que é uma discriminated union?

Uma union de tipos de objeto que compartilham uma propriedade "tag" literal. Verificar a tag estreita o valor para um membro, e uma verificação com never no ramo default faz o compilador apontar qualquer case que você esquecer.

15. Qual é a diferença entre as e satisfies?

value as T é uma type assertion: diz ao compilador para tratar o valor como T e pula a maior parte das verificações. value satisfies T verifica o valor contra T, mas mantém o tipo próprio do valor, mais preciso.

type Theme = { primary: string; secondary: string };

const a = { primary: "#07f" } as Theme;        // compiles: the missing key is not reported
const b = { primary: "#07f" } satisfies Theme; // error TS2741: Property 'secondary' is missing
const c = {} as { name: string };              // compiles; c.name is undefined at run time

Quando o objeto está completo, satisfies também mantém o tipo inferido dele: verificada contra Record<string, string>, a variável continua sabendo exatamente quais chaves tem, enquanto uma anotação a alargaria para qualquer chave string.

16. O que o operador ! faz depois de uma variável?

É a non-null assertion: el! remove null e undefined do tipo. Ela não gera nenhuma verificação, então, se o valor for de fato null, o programa quebra no ponto em que ele é usado. Prefira ?., ?? ou um if explícito.

17. Qual é a diferença entre private e #private?

private é garantido só pelo compilador; a propriedade é uma propriedade comum na saída JavaScript. #field é um campo privado do JavaScript, garantido pelo runtime.

protected funciona como private, mas também permite acesso a partir de subclasses, e readonly proíbe reatribuição depois da construção.

18. Qual é a diferença entre uma classe abstrata e uma interface?

Uma interface é só um tipo: descreve um formato e some da saída. Uma classe abstrata é uma classe de verdade que não pode ser instanciada; ela pode ter métodos implementados, campos e construtores ao lado de membros abstract que as subclasses precisam implementar. Uma classe pode implementar várias interfaces, mas estender só uma classe.

abstract class Repository<T> {
    protected items: T[] = [];
    abstract validate(item: T): boolean; // subclasses must implement
    add(item: T): void {                 // shared implementation
        if (this.validate(item)) this.items.push(item);
    }
}

19. O que é sobrecarga de funções no TypeScript?

Várias assinaturas de chamada seguidas de uma implementação cuja assinatura é compatível com todas elas. Quem chama só enxerga as sobrecargas, então cada chamada recebe um tipo de retorno preciso.

function parse(value: string): number;
function parse(value: string[]): number[];
function parse(value: string | string[]): number | number[] {
    return Array.isArray(value) ? value.map(Number) : Number(value);
}

const one = parse("4");          // number
const many = parse(["1", "2"]);  // number[]

Quando o tipo de retorno não depende do tipo do argumento, uma única assinatura com um parâmetro union é mais simples.

Perguntas avançadas

20. O que é tipagem estrutural?

O TypeScript compara tipos pelo formato, não pelo nome. Qualquer valor com as propriedades exigidas é aceito, mesmo que nunca tenha sido declarado com aquele tipo.

O color extra não é problema aqui porque pixel é uma variável. Passar o objeto literal diretamente, show({ x: 3, y: 4, color: "red" }), é um erro de propriedade excedente, uma verificação que vale só para literais novos. Quando dois tipos com o mesmo formato não podem se misturar (um UserId e um OrderId que são ambos strings), use um branded type: type UserId = string & { readonly __brand: "UserId" }.

21. Como você implementaria Readonly e Partial?

Com mapped types: percorra keyof T e adicione um modificador a cada propriedade.

type MyReadonly<T> = { readonly [K in keyof T]: T[K] };
type MyPartial<T> = { [K in keyof T]?: T[K] };
type Mutable<T> = { -readonly [K in keyof T]: T[K] }; // "-" removes a modifier

type User = { name: string; age: number };
type Draft = MyPartial<User>; // { name?: string; age?: number }

22. O que são conditional types e infer?

T extends U ? X : Y escolhe um tipo com base em uma condição. Dentro da condição, infer declara uma variável de tipo que captura parte do tipo correspondente. Conditional types se distribuem sobre unions.

type MyReturnType<F> = F extends (...args: any[]) => infer R ? R : never;
type ElementOf<T> = T extends (infer E)[] ? E : T;

type A = MyReturnType<() => Promise<number>>; // Promise<number>
type B = ElementOf<string[]>;                 // string
type C = ElementOf<number | boolean[]>;       // number | boolean (distributed)

Mais padrões estão na página de conditional types.

23. O que é um arquivo .d.ts e o que declare faz?

Um arquivo de declaração contém só os tipos de um código que existe em outro lugar, como uma biblioteca JavaScript ou as APIs do navegador. declare afirma que um valor existe sem criá-lo: declare const VERSION: string; não gera nada na compilação. Os tipos de bibliotecas vêm junto com o pacote ou de pacotes @types/{name}, e o tsc gera arquivos .d.ts para o seu próprio código com declaration: true.

24. O que strict faz e quais opções do tsconfig importam mais?

"strict": true ativa noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables e strictBuiltinIteratorReturn. No TypeScript 7 ele vem ativado por padrão. As outras opções sobre as quais os entrevistadores perguntam:

OpçãoResposta em uma linha
targetqual versão do JavaScript a saída usa
moduleo formato de módulo da saída: nodenext segue as regras do Node, esnext/preserve mantêm import para um bundler
moduleResolutioncomo os imports são encontrados: nodenext exige ./file.js em arquivos ES module, bundler aceita ./file
noUncheckedIndexedAccessarr[i] inclui undefined no tipo
pathsaliases de import só para o verificador de tipos; a saída mantém o alias, então um bundler ou o campo imports do Node precisa resolvê-lo
skipLibChecknão verifica arquivos .d.ts, para ganhar velocidade
verbatimModuleSyntaximports usados só como tipos precisam ser marcados com type; os outros imports são mantidos como foram escritos

25. O que é o TypeScript 7?

O compilador do TypeScript reescrito em Go como um programa nativo, lançado como a versão 7 do pacote npm typescript. O comando continua sendo tsc e a linguagem é a mesma, mas ele é muito mais rápido que o compilador 6.x baseado em JavaScript: o time do TypeScript relata ganhos de 8x a 12x em builds completos típicos, graças ao código nativo e ao multithreading com memória compartilhada. Ele também aplica as remoções que o 6.0 havia marcado como obsoletas; por exemplo, baseUrl, outFile, moduleResolution: "node10", module: "amd" e alwaysStrict: false agora são erros (TS5102, TS5108) que pedem para você removê-los.

Perguntas frequentes

Quais são as perguntas de entrevista de TypeScript mais comuns?

As que mais aparecem: a diferença entre any e unknown, interface vs type, como generics funcionam, como funcionam narrowing e type guards, o que fazem utility types como Partial, Pick e Omit, e se o TypeScript verifica tipos em tempo de execução (não verifica).

Que perguntas de TypeScript são feitas para desenvolvedores sêniores?

Espere escrever tipos, não só ler: implementar Readonly ou ReturnType com mapped e conditional types, explicar tipagem estrutural e quando usar branded types, projetar uma discriminated union com verificação exaustiva e discutir escolhas de tsconfig como strict, noUncheckedIndexedAccess e resolução de módulos.

Como me preparar para uma entrevista de TypeScript?

Escreva programas pequenos com strict ativado e leia os erros do compilador até conseguir prevê-los. Saiba explicar narrowing, generics com restrições, os principais utility types e por que type assertions são inseguras, cada um com um exemplo de duas linhas.

TypeScript cai em entrevistas de React e Angular?

Normalmente sim. O próprio Angular é escrito em TypeScript e as aplicações Angular também, então entrevistas de Angular costumam pressupor TypeScript, incluindo decorators como @Component e modificadores de acesso. Entrevistas de React para um projeto em TypeScript costumam pedir para tipar props, estado e handlers de eventos, o que usa as mesmas interfaces, unions e generics mostrados aqui.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR