{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}strict: true включает целый пакет проверок одной строкой:
{
"compilerOptions": {
"strict": true
// Эквивалентно включению всех этих опций:
// "strictNullChecks": true — null/undefined не присваиваются другим типам
// "noImplicitAny": true — нельзя иметь неявный any
// "strictFunctionTypes": true — строгая проверка типов функций
// "strictBindCallApply": true — проверка bind/call/apply
// "strictPropertyInitialization": true — свойства класса должны быть инициализированы
// "noImplicitThis": true — this должен иметь явный тип
// "alwaysStrict": true — добавляет "use strict" в каждый файл
}
}Определяет какой JavaScript на выходе:
{
"compilerOptions": {
"target": "ES5" // IE совместимость — стрелки → function, let → var
"target": "ES2015" // async/await, классы, стрелки
"target": "ES2020" // optional chaining, nullish coalescing
"target": "ES2022" // top-level await, private fields (#)
"target": "ESNext" // самые новые возможности
}
}{
"compilerOptions": {
// Формат модулей в скомпилированном коде:
"module": "CommonJS", // require/module.exports — Node.js
"module": "ESNext", // import/export — браузеры и современный Node
"module": "Node16", // для Node.js 16+ с .mjs/.cjs
// Как TypeScript ищет модули:
"moduleResolution": "bundler", // для Vite/webpack (современный)
"moduleResolution": "node16", // для Node.js 16+
"moduleResolution": "node" // классический Node.js алгоритм
}
}{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"]
}
}
}// Теперь вместо:
import { Button } from '../../../components/Button'
// Можно:
import { Button } from '@components/Button'Для Node.js:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"esModuleInterop": true
}
}Для React (Vite):
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"]
}
}Для монорепо (`composite`):
{
"compilerOptions": {
"composite": true, // Включает инкрементальную сборку
"declaration": true, // Генерирует .d.ts файлы
"declarationMap": true // Source maps для .d.ts
}
}{
"compilerOptions": {
"lib": ["ES2020", "DOM"], // Какие встроенные типы доступны
"jsx": "react-jsx", // Как обрабатывать JSX
"sourceMap": true, // Генерировать source maps
"declaration": true, // Генерировать .d.ts файлы
"noUnusedLocals": true, // Ошибка на неиспользуемые переменные
"noUnusedParameters": true, // Ошибка на неиспользуемые параметры
"exactOptionalPropertyTypes": true // Точные опциональные типы
}
}Симуляция tsconfig: объект конфигурации с профилями, validateConfig и mergeConfigs — паттерны конфигурирования в JS
// tsconfig.json — это просто JSON-конфиг для TypeScript компилятора.
// В JS симулируем те же концепции: профили конфигурации,
// валидацию и слияние настроек.
// Базовые профили конфигурации (аналоги рекомендуемых tsconfig)
const CONFIG_PROFILES = {
base: {
strict: true,
sourceMap: true,
declaration: true,
noUnusedLocals: true,
noUnusedParameters: true,
},
node: {
target: 'ES2022',
module: 'CommonJS',
moduleResolution: 'node',
outDir: './dist',
rootDir: './src',
esModuleInterop: true,
},
react: {
target: 'ES2020',
module: 'ESNext',
moduleResolution: 'bundler',
jsx: 'react-jsx',
lib: ['ES2020', 'DOM', 'DOM.Iterable'],
},
nextjs: {
target: 'ES2017',
module: 'ESNext',
moduleResolution: 'bundler',
jsx: 'preserve',
lib: ['DOM', 'DOM.Iterable', 'ESNext'],
allowJs: true,
skipLibCheck: true,
forceConsistentCasingInFileNames: true,
}
}
// Функция слияния конфигов (base перекрывается override)
function mergeConfigs(...configs) {
return configs.reduce((acc, config) => {
const result = Object.assign({}, acc)
Object.keys(config).forEach(key => {
if (Array.isArray(config[key]) && Array.isArray(acc[key])) {
// Массивы (например lib) объединяются без дублей
result[key] = [...new Set([...acc[key], ...config[key]])]
} else {
result[key] = config[key]
}
})
return result
}, {})
}
// Валидация совместимости настроек
function validateConfig(config) {
const errors = []
const warnings = []
// Проверка совместимости target и module
if (config.module === 'CommonJS' && config.target === 'ESNext') {
warnings.push('module: CommonJS с target: ESNext — нестандартная комбинация')
}
// Рекомендуем strict для production
if (!config.strict) {
warnings.push('Рекомендуется включить strict: true')
}
// jsx требует react или react-jsx
if (config.jsx && !['react', 'react-jsx', 'react-jsxdev', 'preserve'].includes(config.jsx)) {
errors.push(`Неверное значение jsx: "${config.jsx}"`)
}
return { valid: errors.length === 0, errors, warnings }
}
// --- Демонстрация ---
console.log('=== Профиль Node.js ===')
const nodeConfig = mergeConfigs(CONFIG_PROFILES.base, CONFIG_PROFILES.node)
console.log(JSON.stringify(nodeConfig, null, 2))
console.log('\n=== Профиль React ===')
const reactConfig = mergeConfigs(CONFIG_PROFILES.base, CONFIG_PROFILES.react)
console.log('target:', reactConfig.target)
console.log('jsx:', reactConfig.jsx)
console.log('lib:', reactConfig.lib)
console.log('\n=== Валидация ===')
const badConfig = { module: 'CommonJS', target: 'ESNext', jsx: 'invalid' }
const { valid, errors, warnings } = validateConfig(badConfig)
console.log('valid:', valid)
console.log('errors:', errors)
console.log('warnings:', warnings)
const goodConfig = mergeConfigs(CONFIG_PROFILES.base, CONFIG_PROFILES.node)
const result = validateConfig(goodConfig)
console.log('\nNode config valid:', result.valid)
console.log('warnings:', result.warnings){
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}strict: true включает целый пакет проверок одной строкой:
{
"compilerOptions": {
"strict": true
// Эквивалентно включению всех этих опций:
// "strictNullChecks": true — null/undefined не присваиваются другим типам
// "noImplicitAny": true — нельзя иметь неявный any
// "strictFunctionTypes": true — строгая проверка типов функций
// "strictBindCallApply": true — проверка bind/call/apply
// "strictPropertyInitialization": true — свойства класса должны быть инициализированы
// "noImplicitThis": true — this должен иметь явный тип
// "alwaysStrict": true — добавляет "use strict" в каждый файл
}
}Определяет какой JavaScript на выходе:
{
"compilerOptions": {
"target": "ES5" // IE совместимость — стрелки → function, let → var
"target": "ES2015" // async/await, классы, стрелки
"target": "ES2020" // optional chaining, nullish coalescing
"target": "ES2022" // top-level await, private fields (#)
"target": "ESNext" // самые новые возможности
}
}{
"compilerOptions": {
// Формат модулей в скомпилированном коде:
"module": "CommonJS", // require/module.exports — Node.js
"module": "ESNext", // import/export — браузеры и современный Node
"module": "Node16", // для Node.js 16+ с .mjs/.cjs
// Как TypeScript ищет модули:
"moduleResolution": "bundler", // для Vite/webpack (современный)
"moduleResolution": "node16", // для Node.js 16+
"moduleResolution": "node" // классический Node.js алгоритм
}
}{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"]
}
}
}// Теперь вместо:
import { Button } from '../../../components/Button'
// Можно:
import { Button } from '@components/Button'Для Node.js:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"esModuleInterop": true
}
}Для React (Vite):
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"]
}
}Для монорепо (`composite`):
{
"compilerOptions": {
"composite": true, // Включает инкрементальную сборку
"declaration": true, // Генерирует .d.ts файлы
"declarationMap": true // Source maps для .d.ts
}
}{
"compilerOptions": {
"lib": ["ES2020", "DOM"], // Какие встроенные типы доступны
"jsx": "react-jsx", // Как обрабатывать JSX
"sourceMap": true, // Генерировать source maps
"declaration": true, // Генерировать .d.ts файлы
"noUnusedLocals": true, // Ошибка на неиспользуемые переменные
"noUnusedParameters": true, // Ошибка на неиспользуемые параметры
"exactOptionalPropertyTypes": true // Точные опциональные типы
}
}Симуляция tsconfig: объект конфигурации с профилями, validateConfig и mergeConfigs — паттерны конфигурирования в JS
// tsconfig.json — это просто JSON-конфиг для TypeScript компилятора.
// В JS симулируем те же концепции: профили конфигурации,
// валидацию и слияние настроек.
// Базовые профили конфигурации (аналоги рекомендуемых tsconfig)
const CONFIG_PROFILES = {
base: {
strict: true,
sourceMap: true,
declaration: true,
noUnusedLocals: true,
noUnusedParameters: true,
},
node: {
target: 'ES2022',
module: 'CommonJS',
moduleResolution: 'node',
outDir: './dist',
rootDir: './src',
esModuleInterop: true,
},
react: {
target: 'ES2020',
module: 'ESNext',
moduleResolution: 'bundler',
jsx: 'react-jsx',
lib: ['ES2020', 'DOM', 'DOM.Iterable'],
},
nextjs: {
target: 'ES2017',
module: 'ESNext',
moduleResolution: 'bundler',
jsx: 'preserve',
lib: ['DOM', 'DOM.Iterable', 'ESNext'],
allowJs: true,
skipLibCheck: true,
forceConsistentCasingInFileNames: true,
}
}
// Функция слияния конфигов (base перекрывается override)
function mergeConfigs(...configs) {
return configs.reduce((acc, config) => {
const result = Object.assign({}, acc)
Object.keys(config).forEach(key => {
if (Array.isArray(config[key]) && Array.isArray(acc[key])) {
// Массивы (например lib) объединяются без дублей
result[key] = [...new Set([...acc[key], ...config[key]])]
} else {
result[key] = config[key]
}
})
return result
}, {})
}
// Валидация совместимости настроек
function validateConfig(config) {
const errors = []
const warnings = []
// Проверка совместимости target и module
if (config.module === 'CommonJS' && config.target === 'ESNext') {
warnings.push('module: CommonJS с target: ESNext — нестандартная комбинация')
}
// Рекомендуем strict для production
if (!config.strict) {
warnings.push('Рекомендуется включить strict: true')
}
// jsx требует react или react-jsx
if (config.jsx && !['react', 'react-jsx', 'react-jsxdev', 'preserve'].includes(config.jsx)) {
errors.push(`Неверное значение jsx: "${config.jsx}"`)
}
return { valid: errors.length === 0, errors, warnings }
}
// --- Демонстрация ---
console.log('=== Профиль Node.js ===')
const nodeConfig = mergeConfigs(CONFIG_PROFILES.base, CONFIG_PROFILES.node)
console.log(JSON.stringify(nodeConfig, null, 2))
console.log('\n=== Профиль React ===')
const reactConfig = mergeConfigs(CONFIG_PROFILES.base, CONFIG_PROFILES.react)
console.log('target:', reactConfig.target)
console.log('jsx:', reactConfig.jsx)
console.log('lib:', reactConfig.lib)
console.log('\n=== Валидация ===')
const badConfig = { module: 'CommonJS', target: 'ESNext', jsx: 'invalid' }
const { valid, errors, warnings } = validateConfig(badConfig)
console.log('valid:', valid)
console.log('errors:', errors)
console.log('warnings:', warnings)
const goodConfig = mergeConfigs(CONFIG_PROFILES.base, CONFIG_PROFILES.node)
const result = validateConfig(goodConfig)
console.log('\nNode config valid:', result.valid)
console.log('warnings:', result.warnings)Реализуй `ConfigBuilder` — builder паттерн для конфигурации TypeScript. Методы: `setTarget(target)` задаёт target, `enableStrict()` включает strict, `setOutDir(dir)` задаёт outDir, `addPath(alias, path)` добавляет в paths, `build()` возвращает итоговый объект конфига. Все методы кроме build() возвращают this для chaining.
Каждый метод-модификатор должен менять this._config.compilerOptions и возвращать this. В addPath: this._config.compilerOptions.paths[alias] = [path]. В build(): return JSON.parse(JSON.stringify(this._config)) чтобы вернуть независимую копию.
Токены для AI-помощника закончились
Купи токены чтобы задавать вопросы AI прямо в уроке