TypeScript in practice

TypeScript in practice

How senior interviews test TypeScript — as a design tool rather than a syntax quiz — and how the pages on the type system, generics, Vue and Nuxt typing, configuration and TypeScript 7, runtime validation and typing smells fit together.

Every Nuxt job in 2026 is a TypeScript job, and the interview question is rarely "what is a generic". It is "type this API response so the wrong usage does not compile", "why does this as cast hide a bug", or "how does the type reach the template". TypeScript 7.0, the Go-based compiler, shipped on 8 July 2026 and made type checking roughly ten times faster without changing the language; knowing what it changed in configuration and what it means for Vue tooling is part of being current.

Know

  • Types are a design tool. The point is to make illegal states unrepresentable: discriminated unions instead of boolean flags, unknown at boundaries instead of any, literal types instead of stringly-typed options. A senior candidate talks about types as the API contract of a module or component.
  • Types are erased. Nothing checks at runtime; JSON from an API is unknown until a schema validates it. The runtime validation page is where "TypeScript makes it safe" is corrected.
  • Inference does most of the work. Good TypeScript has few annotations: infer from values, from as const, from schemas (z.infer), from framework macros (defineProps<T>). Generics exist to preserve information through a function, not to decorate it.
  • The framework layer has its own idioms: Vue's compiler macros and utility types, Nuxt's generated types under .nuxt/ (auto-imports, components, typed routes, typed $fetch from server routes, runtimeConfig augmentation), and project references that split app, server and shared type contexts.
  • Configuration decides strictness and performance: strict (plus noUncheckedIndexedAccess), verbatimModuleSyntax, moduleResolution: 'bundler', isolatedModules, erasableSyntaxOnly for Node's native type stripping, and the TS 7 defaults and removals.
  • TypeScript 7: a native port (Go), identical type-checking semantics to 6.0, 8–12× faster full builds, multithreaded checking (--checkers), new defaults (strict: true, module: esnext, types: [], rootDir: ./), removed legacy options (baseUrl, moduleResolution: node10, target: es5), and a language server rewrite. Vue template checking through the compiler API arrives with 7.1, so Vue projects still run vue-tsc on TypeScript 6 while the tooling catches up (verify).

How the pages fit

PageQuestion it answers
Type system fundamentalsStructural typing, unknown/never, narrowing, literal types, satisfies, strictness
Generics and inferenceConstraints, infer, conditional and mapped types, template literals, NoInfer, when generics are too much
TypeScript with Vue and NuxtMacros, generic components, Nuxt's generated types, typed $fetch, augmentation
Modules, declarations and configtsconfig essentials, .d.ts authoring, project references, TypeScript 7 changes
Runtime validation and type safetySchemas at boundaries, z.infer, branded types, exhaustive checks, error typing
Typing patterns and smellsThe patterns seniors use and the casts, anys and over-generic helpers they flag in review

How it works

The interview task in miniature: an API client whose misuse does not compile.

shared/api/client.ts
import { z } from 'zod'

// The response contract exists once, as a schema; the type is derived.
export const productSchema = z.object({
  id: z.string(),
  name: z.string(),
  status: z.enum(['draft', 'published', 'archived']),
  price: z.object({ amount: z.number().int(), currency: z.string().length(3) }),
})
export type Product = z.infer<typeof productSchema>

// Illegal states are unrepresentable: a result is either ok with data or an error with a message, never both.
export type Result<T> = { ok: true, data: T } | { ok: false, error: { status: number, message: string } }

export async function getProduct(id: string): Promise<Result<Product>> {
  try {
    const raw: unknown = await $fetch(`/api/products/${id}`) // unknown until validated
    return { ok: true, data: productSchema.parse(raw) }
  }
  catch (e) {
    const status = typeof e === 'object' && e && 'status' in e ? Number((e as { status: unknown }).status) : 500
    return { ok: false, error: { status, message: e instanceof Error ? e.message : 'Unknown error' } }
  }
}

// Usage: the compiler forces the check before data is touched.
const result = await getProduct('1')
if (result.ok) console.log(result.data.name)
else console.error(result.error.status)
Gotcha· Confusing TypeScript knowledge with TypeScript fluency

Knowing infer and keyof is not the skill; recognising that a component with type: string should be type: 'primary' | 'secondary' and that a data as Product cast after a fetch is a lie, is. Interviewers probe judgement with code review prompts far more often than with type puzzles.

Exercise

Exercise
  • Take one API call in a project you own that casts the response (as Foo), replace it with a schema parse and a Result type, and count the call sites the compiler now forces you to fix.
  • Run tsc --extendedDiagnostics on a project with TypeScript 6 and, if available, tsgo (TypeScript 7), and compare check times.

Be able to say

Be able to say· How do you use TypeScript day to day, beyond annotating parameters?

"As the design layer of the code. I model state with discriminated unions so impossible combinations do not compile, type boundaries as unknown and validate them with a schema that also produces the type, derive types from values with as const and satisfies instead of declaring them twice, and reach for generics only when a function needs to preserve information through it. In Vue and Nuxt that means typed props, emits and slots through the macros, generic components, typed routes and $fetch from the generated types, and nuxt typecheck in CI because the build alone does not check. And I keep the compiler fast: strict but not clever, no deep conditional-type gymnastics in application code."

Your notes

Open in Notes

Nothing yet. Notes filed here show up on every page of this section.