Menu

tsconfig.json explicado: opciones, valores por defecto y ejemplos

tsconfig.json marca una carpeta como proyecto TypeScript y fija las opciones del compilador. Las opciones que importan (target, module, moduleResolution, strict, rootDir, outDir, include, lib, types, noEmit, skipLibCheck), una configuración inicial recomendada, extends y qué cambió TypeScript 7.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

tsconfig.json es el archivo de configuración de un proyecto TypeScript. Cuando ejecutas tsc sin argumentos, el compilador lo busca en la carpeta actual (y luego en las carpetas padre), lee las opciones de compilerOptions y comprueba los archivos que indica include. Uno pequeño pero completo:

{
    "compilerOptions": {
        "target": "es2022",
        "module": "nodenext",
        "strict": true,
        "rootDir": "./src",
        "outDir": "./dist"
    },
    "include": ["src"]
}

Esto compila todos los archivos TypeScript de src a JavaScript en dist, como código ES2022, con las reglas de módulos de Node.js y todas las comprobaciones estrictas activadas. npx tsc --init genera un archivo inicial más largo con un comentario en cada opción.

El archivo es JSON con comentarios: se aceptan los comentarios //, los comentarios /* */ y las comas finales.

Una configuración inicial recomendada

Para una aplicación o un script de Node.js:

{
    "compilerOptions": {
        "rootDir": "./src",
        "outDir": "./dist",

        "target": "es2024",
        "lib": ["es2024"],
        "module": "nodenext",
        "types": ["node"],

        "strict": true,
        "noUncheckedIndexedAccess": true,
        "verbatimModuleSyntax": true,
        "skipLibCheck": true,
        "sourceMap": true
    },
    "include": ["src"]
}

Necesita npm install --save-dev @types/node para los tipos de Node.js. Con module: "nodenext", el campo "type" de package.json decide si un archivo .ts es un módulo ES ("type": "module") o CommonJS ("type": "commonjs", que es lo que escribe npm init -y). Usa "type": "module" en proyectos nuevos que usen import y export.

Para código que construye un bundler como Vite, esbuild o webpack, el bundler escribe el JavaScript y tsc solo comprueba:

{
    "compilerOptions": {
        "target": "es2022",
        "lib": ["es2022", "dom"],
        "module": "preserve",
        "noEmit": true,

        "strict": true,
        "noUncheckedIndexedAccess": true,
        "verbatimModuleSyntax": true,
        "isolatedModules": true,
        "skipLibCheck": true,
        "jsx": "react-jsx"
    },
    "include": ["src"]
}

Las plantillas de los frameworks (Vite, Next.js, Angular) generan su propio tsconfig.json. Parte del suyo en lugar de sustituirlo.

Las opciones que importan

OpciónQué haceValor por defecto en TypeScript 7
targetVersión de JavaScript de la salida; la sintaxis nueva se reescribe para targets antiguoses2025
libTipos de las APIs integradas que conoce el comprobador (Array.prototype.at, Map, document)Coincide con target, más el DOM
moduleTipo de código de módulos que se genera y reglas de módulos que se aplicanesnext
moduleResolutionCómo se encuentran en disco las rutas de importnodenext o node16 con el module correspondiente, si no bundler
strictActiva toda la familia de comprobaciones estrictastrue
rootDirCarpeta cuya estructura se replica en outDirLa carpeta que contiene tsconfig.json
outDirDónde van los archivos .js (y .d.ts)Junto a cada archivo fuente
include / exclude / filesQué archivos forman parte del proyectoTodos los archivos .ts bajo la carpeta
typesQué paquetes @types se cargan sin un import[], ninguno
noEmitSolo comprobar, no escribir nadafalse
declarationEscribir también archivos de declaración de tipos .d.tsfalse
sourceMapEscribir archivos .js.map para los depuradoresfalse
esModuleInteropPermite que import x from "cjs-package" funcione con paquetes CommonJStrue (no se puede desactivar)
skipLibCheckOmite la comprobación de tipos de los archivos .d.ts, incluidos los de node_modulesfalse

target y lib

target indica en qué versión de JavaScript debe ejecutarse la salida. La sintaxis más nueva que el target se reescribe: con "target": "es2017", un campo de clase o ??= se convierte en código más antiguo. El target más bajo que acepta TypeScript 7 es es2015 (es6); es5 se eliminó.

target no añade las APIs de ejecución que falten. Describirlas es trabajo de lib, y aportarlas es trabajo de un polyfill. lib le dice al comprobador qué objetos y métodos integrados existen. Su valor por defecto sigue a target e incluye también los tipos del DOM del navegador, así que document pasa la comprobación incluso en un proyecto de Node.js salvo que fijes lib tú mismo. Usar un método de un estándar más nuevo que tu lib es un error de compilación:

src/b.ts(1,24): error TS2550: Property 'toSorted' does not exist on type 'number[]'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2023' or later.

Los ejemplos ejecutables de esta documentación usan el lib es2022, así que toSorted, Object.groupBy y los nuevos métodos de Set no están disponibles en ellos.

module y moduleResolution

module tiene tres valores razonables para código nuevo:

  • nodenext: para código que ejecuta Node.js. Cada archivo es ESM o CommonJS según su extensión (.mts, .cts) o el "type" del package.json más cercano, exactamente como decide Node. Los imports relativos en los módulos ES necesitan extensión de archivo, escrita como .js aunque el código fuente sea .ts: import { add } from "./math.js". moduleResolution se ajusta automáticamente.
  • preserve: para código que procesa un bundler. Los imports se dejan tal como se escribieron, y la resolución usa las reglas de bundler, que permiten imports sin extensión.
  • esnext: salida de módulos ES sin más, con resolución bundler. Es el valor por defecto cuando no se fija module.

Un primer error habitual con la configuración de tsc --init viene de que npm init -y escribe "type": "commonjs":

src/main.ts(1,10): error TS1295: ECMAScript imports and exports cannot be written in a CommonJS file under 'verbatimModuleSyntax'.

El archivo usa import, pero package.json dice que el proyecto es CommonJS. Cambia "type" a "module". La página de módulos explica en detalle los imports y los exports.

strict y las opciones de comprobación

"strict": true activa de golpe un grupo de comprobaciones: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, strictBuiltinIteratorReturn, noImplicitThis y useUnknownInCatchVariables. Es el valor por defecto en TypeScript 7 y está activado en todos los ejemplos ejecutables de aquí. El código escrito para el modo estricto estrecha el tipo antes de usar un valor que puede faltar:

Sin anotación, el tipo de un parámetro no se puede inferir, y noImplicitAny lo señala:

index.ts(2,17): error TS7006: Parameter 'n' implicitly has an 'any' type.

strict no incluye todas las comprobaciones útiles. Dos que vale la pena añadir son noUncheckedIndexedAccess (un elemento de un array o una búsqueda en una firma de índice tiene el tipo T | undefined) y exactOptionalPropertyTypes (una propiedad opcional no se puede fijar explícitamente a undefined); tsc --init activa las dos. Las comprobaciones de estilo como noUnusedLocals, noImplicitReturns y noFallthroughCasesInSwitch están desactivadas por defecto.

Qué archivos: include, exclude, rootDir, outDir

Sin include ni files, el proyecto contiene todos los archivos .ts, .tsx y .d.ts de la carpeta y sus subcarpetas. node_modules siempre queda fuera. El outDir también, pero solo mientras no hayas fijado exclude: una lista exclude propia sustituye ese valor por defecto, así que añade a ella la carpeta de salida. include y exclude aceptan patrones glob:

{
    "include": ["src", "scripts/**/*.ts"],
    "exclude": ["src/**/*.test.ts"]
}

exclude solo filtra lo que encontró include. Un archivo que importa otro archivo incluido se sigue compilando.

outDir es donde va la salida, y rootDir es la parte del árbol de código fuente que se replica en ella: con "rootDir": "./src", src/api/users.ts se convierte en dist/api/users.js. Fija los dos. rootDir vale por defecto la carpeta que contiene tsconfig.json, así que si solo fijas outDir mientras el código está en src, TypeScript 7 se detiene con:

error TS5011: The common source directory of 'tsconfig.json' is './src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.

Opciones de salida: noEmit, declaration, sourceMap

  • "noEmit": true convierte tsc en un comprobador de tipos puro. Úsalo cuando otra herramienta (un bundler, tsx, el type stripping de Node.js) produce el JavaScript.
  • "declaration": true escribe un archivo .d.ts por módulo, con los tipos y sin el código. Las librerías lo necesitan para que sus usuarios tengan tipos. declarationMap añade mapas para que "ir a la definición" lleve al código .ts.
  • "sourceMap": true escribe archivos .js.map para que los depuradores y las trazas de error apunten a las líneas del .ts.
  • "noEmitOnError": true no escribe nada mientras haya errores de tipo. Sin esta opción, tsc informa de los errores y aun así escribe el JavaScript.

types, esModuleInterop y skipLibCheck

types lista los paquetes @types que se cargan de forma global, sin un import. El valor por defecto de TypeScript 7 es una lista vacía, así que después de npm install --save-dev @types/node también añades "types": ["node"]; si no, process y require siguen siendo desconocidos (error TS2591: Cannot find name 'process'). Los test runners con funciones globales, como el describe de Jest, van en la misma lista.

esModuleInterop hace que funcionen los imports por defecto de paquetes CommonJS (import express from "express"). Siempre está activado en TypeScript 7, y ponerlo a false es un error.

skipLibCheck omite la comprobación de tipos de los archivos de declaración. Acelera los builds y evita errores dentro de node_modules que no puedes corregir, a cambio de no notar los conflictos entre los tipos de dos librerías. La mayoría de proyectos lo activa.

Compartir configuración con extends

extends carga otra configuración y deja que este archivo sobrescriba partes de ella:

{
    "extends": "./tsconfig.base.json",
    "compilerOptions": {
        "rootDir": "./src",
        "outDir": "./dist"
    },
    "include": ["src"]
}

Las compilerOptions se combinan opción por opción, mientras que include, exclude y files de la base se sustituyen, no se combinan, si este archivo los fija. Las rutas del archivo base se resuelven respecto al archivo base. extends también acepta un paquete: el proyecto @tsconfig/bases publica uno por entorno, por ejemplo npm install --save-dev @tsconfig/node24 y luego "extends": "@tsconfig/node24/tsconfig.json".

Para ver la configuración final después de aplicar todos los extends y los valores por defecto, ejecuta:

npx tsc --showConfig

Opciones eliminadas en TypeScript 7

TypeScript 6 marcó estas opciones como obsoletas y TypeScript 7 las eliminó. Una configuración que aún use alguna falla con error TS5108 o TS5102, por ejemplo Option 'baseUrl' has been removed. Please remove it from your configuration.

Opción eliminadaQué usar en su lugar
"target": "es5"es2015 o posterior
"moduleResolution": "node" (node10) o "classic"nodenext o bundler
"module": "amd", "umd", "system", "none"nodenext, esnext o preserve, y un bundler para otros formatos
baseUrlEntradas de paths relativas al archivo tsconfig
outFileUn bundler
downlevelIterationNada: los targets desde es2015 admiten la iteración de forma nativa
"esModuleInterop": false, "allowSyntheticDefaultImports": false, "alwaysStrict": falseQuita la línea; estas opciones siempre están activadas

La página de TypeScript 7 lista los demás cambios de esa versión, incluidos los nuevos valores por defecto que no cubre esta tabla.

Preguntas frecuentes

¿Qué es tsconfig.json?

Es el archivo de configuración de un proyecto TypeScript. Su presencia marca la carpeta como raíz del proyecto, compilerOptions fija cómo comprueba y genera código el compilador, e include, exclude o files indican qué archivos pertenecen al proyecto. Ejecutar tsc sin argumentos lo lee.

¿Cómo creo un archivo tsconfig.json?

Ejecuta npx tsc --init en la carpeta del proyecto (con TypeScript instalado). Escribe un tsconfig.json con la configuración recomendada y un comentario en cada opción. También puedes escribir el archivo a mano; {} es un tsconfig válido que usa todos los valores por defecto.

¿Qué valor debe tener target en tsconfig?

La versión de JavaScript más antigua en la que tiene que ejecutarse tu código. Para un Node.js actual, es2022 o posterior es seguro; el valor por defecto de TypeScript 7 es es2025. target controla qué sintaxis nueva se reescribe para motores antiguos y también elige el lib por defecto, el conjunto de APIs integradas que conoce el comprobador.

¿Qué diferencia hay entre module y moduleResolution?

module decide qué tipo de código de módulos escribe el compilador (import/export de ES o require de CommonJS) y qué reglas de módulos se aplican. moduleResolution decide cómo se encuentra en disco una ruta de import como "./utils.js" o "lodash". Usa nodenext para código que ejecuta Node.js, y module: "preserve" (que implica la resolución bundler) para código que procesa un bundler.

¿Puede tsconfig.json tener comentarios?

Sí. El compilador lo lee como JSON con comentarios: se admiten los comentarios // y /* */ y las comas finales, y por eso tsc --init escribe un archivo lleno de opciones comentadas. Otras herramientas que lo lean como JSON estricto pueden fallar con ellos.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR