暴走的楼房 · 网易市值反超美团,丁磊“闷声发大财” | 投中网· 1 月前 · |
坏坏的啤酒 · 记者观察:青少年热衷“买谷子”,他们到底在买 ...· 1 月前 · |
善良的小蝌蚪 · 【音频政策解读】广州市卫生健康委员会广州市民 ...· 11 月前 · |
深情的毛豆 · 十二条建议“落地生根” ...· 1 年前 · |
我有几个文件我想用脚本编译。这些文件依赖于
paths
编译选项来解析其模块。由于我希望具体针对这些文件,所以我必须将它们提供给
tsc
(因为我不想为这个任务创建一个针对这些文件的单独的
tsconfig.json
)
我看过将
--path
参数传递给
tsc
的选项,但这是不允许的(
error TS6064: Option 'paths' can only be specified in 'tsconfig.json' file.
)
我可以在使用
.ts
选项时只编译特定的
paths
文件吗?
更新(22-06-17)
根据要求,有一些具体的例子:
tsconfig.json
文件中的相关设置如下:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"Components/*": [
"./src/Components/*"
}
因此,相关的部分是路径设置,您可以在其中创建速记,以便从某个目录导入文件。所以您可以导入像
import {header} from 'Components/header.ts'
这样的文件,而不是
import {header} from '../../Components/header.ts'
。
但是我需要从命令行编译特定的文件。但如果我尝试:
tsc --project tsconfig.json entryFile.ts
它会给我一个错误:
error TS5042: Option 'project' cannot be mixed with source files on a command line.
如果我试图向cli提供
paths
选项,就会得到以下错误:
error TS6064: Option 'paths' can only be specified in 'tsconfig.json' file.
指定命令行上的输入文件会使您的tsconfig.json无效。
当在命令行上指定输入文件时,tsconfig.json文件将被忽略。
来自 TypeScript文档 。
因此,除了使用带有文件的适当“包含”(或排除)规范的tsconfig.json之外,没有其他选项。好消息是,在同一个文档中,您会发现:
tsconfig.json文件可以使用扩展属性从另一个文件继承配置。
因此,您可以做的是用如下所示的内容覆盖tsconfig的include属性:
{
"extends": "./tsconfig.json",
"include": [
"src/root/index.ts"
}
所以你可以做一个脚本:
tsc
调用
--project
人们可能会争辩说,这是非常复杂的,并质疑他们为什么决定不适当地支持这种情况。然而,问题仍然存在,为什么我们只想编译一个项目的一个文件。在开发过程中,您可以使用watch (
-w
)选项来编译更改文件,并且在构建完整的项目时,您可能希望完全编译完整的项目。
只是为了巩固@Bram的答案..。
我在我的项目中所做的是有两件事:
project/
dist/
docs/
package.json
tsconfig.json
tsconfig-build.json
所以我有一个
tsconfig-build.json
(因为我不希望
docs/
包含在我的构建中):
// tsconfig-build.json
"extends": "./tsconfig.json",
"include": [
"src/**/*"
}
那么您可以在
package.json
中使用一行
// package.json
"scripts": {
"build": "tsc --p tsconfig-build.json"
},
我也需要确保项目使用
皮棉
进行编译。如果允许
tsconfig.json
和文件路径的组合,您可以直接使用
"tsc"
作为一个分阶段的命令。
作为解决办法,我创建了下面的助手脚本
scripts/tsc-lint.sh
#!/bin/bash -e
TMP=.tsconfig-lint.json
cat >$TMP <<EOF
"extends": "./tsconfig.json",
"include": [
for file in "$@"; do
echo " \"$file\"," >> $TMP
cat >>$TMP <<EOF
"unused"
tsc --project $TMP --skipLibCheck --noEmit
然后,分阶段配置包含:
"lint-staged": {
"{src,tests}/**/*.ts": [
"scripts/tsc-lint.sh"
},
.tsconfig-lint.json
文件被添加到
.gitignore
中。
我正是使用编译器API实现了这一点。这是一个(很大程度上)修改的 它们的最小编译器示例 版本。
import * as ts from 'typescript';
import * as fs from 'fs';
import * as path from 'path';
import * as cp from 'child_process';
import * as dm from '../src-ts/deep-merge-objects';
function compile(fileNames: string[], options: ts.CompilerOptions): void {
const program = ts.createProgram(fileNames, options);
const emitResult = program.emit();
const allDiagnostics = ts
.getPreEmitDiagnostics(program)
.concat(emitResult.diagnostics);
allDiagnostics.forEach((diagnostic) => {
if (diagnostic.file) {
const {line, character} = diagnostic.file.getLineAndCharacterOfPosition(
diagnostic.start!
const message = ts.flattenDiagnosticMessageText(
diagnostic.messageText,
console.log(
`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`
} else {
console.log(
ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')
const exitCode = emitResult.emitSkipped ? 1 : 0;
console.log(`Process exiting with code '${exitCode}'.`);
process.exit(exitCode);
function main(): void {
fs.mkdirSync('./dev-out',{recursive:true})
cp.execSync('cp -r ./testlib-js ./dev-out/');
const tscfgFilenames = [
'@tsconfig/node14/tsconfig.json',
path.join(process.cwd(), 'tsconfig.base.json'),
path.join(process.cwd(), 'tsconfig.json'),
const tscfg = tscfgFilenames.map((fn) => require(fn).compilerOptions);
const compilerOptions: ts.CompilerOptions = dm.deepMerge(
dm.deepMergeInnerDedupeArrays,
...tscfg
if (compilerOptions.lib && compilerOptions.lib.length)
compilerOptions.lib = compilerOptions.lib.map((s) => 'lib.' + s + '.d.ts');
console.log(JSON.stringify(compilerOptions, null, 2));
compile(process.argv.slice(2), compilerOptions);
try {
main();
if (process.exitCode === 1) console.log('compiler produced no output');
} catch (e) {
console.error(e.message);
process.exitCode = 2;
}
抓到的是
compilerOptions.lib
条目
if (compilerOptions.lib && compilerOptions.lib.length)
compilerOptions.lib = compilerOptions.lib.map((s) => 'lib.' + s + '.d.ts');
例如,"es2020“改为"lib.es2020.d.ts”。
泛型对象合并代码如下:
// adapted from adrian-marcelo-gallardo
// https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6#gistcomment-3257606
type objectType = Record<string, any>;
export const isObject = (obj: unknown): obj is objectType => {
return <boolean>obj && typeof obj === 'object';
export function deepMerge(
deepMergeInner: (target: objectType, source: objectType) => objectType,
...objects: objectType[]
): objectType {
if (objects.length === 0) return {};
if (objects.length === 1) return objects[0];
if (objects.some((object) => !isObject(object))) {
throw new Error('deepMerge: all values should be of type "object"');
const target = objects.shift() as objectType;
//console.log(JSON.stringify(target,null,2))
let source: objectType;
while ((source = objects.shift() as objectType)) {
deepMergeInner(target, source);
//console.log(JSON.stringify(target,null,2))
return target;
export function deepMergeInnerDedupeArrays(
target: objectType,
source: objectType
): objectType {
function uniquify(a: any[]): any[] {
return a.filter((v, i) => a.indexOf(v) === i);
Object.keys(source).forEach((key: string) => {
const targetValue = target[key];
const sourceValue = source[key];
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
target[key] = uniquify(targetValue.concat(sourceValue));
} else if (isObject(targetValue) && Array.isArray(sourceValue)) {
target[key] = sourceValue;
} else if (Array.isArray(targetValue) && isObject(sourceValue)) {
target[key] = sourceValue;
} else if (isObject(targetValue) && isObject(sourceValue)) {
target[key] = deepMergeInnerDedupeArrays(
Object.assign({}, targetValue),
sourceValue
} else {
target[key] = sourceValue;
return target;
}
另一种是目录结构。除非使用
compilerOptions.rootDir
,否则不可能获得与get相同的输出目录和所有文件。典型情况是:
"compilerOptions": {
"outDir": "dev-out",
"rootDir": "./"
},
阅读关于 rootDir在这里。 的文章
--noResolve
是这里的关键:
https://www.typescriptlang.org/tsconfig/#noResolve
例如:
// tsconfig.myFile.json
// "extends": "./tsconfig.json",
"include": [
"myFile.ts"
"compilerOptions": {
"noResolve": true
}
$ tsc --project tsconfig.myFile.json
还有一些方法可以包含
--noResolve
和一些输出标志,这样就可以只使用命令行。
基于@sampo的回答。
我们可以在每个包目录中创建一个临时
.tsconfig-lint.json
,其中包括属于每个目录下的阶段性TS文件的列表。
它将为每个包运行一个
tsc
,并报告任何不是0的状态代码。
// <root>/tsc-lint.js
// Usage: `yarn lint-staged` (doesn't support --relative)
// In package.json."lint-staged"."*.{ts,tsx}": `node ./tsc-lint.js`
// Run from workspace root
const chalk = require('chalk');
const spawn = require('cross-spawn');
const fs = require('fs');
const path = require('path');
// Relative path of package locations (relative to root)
const packages = [
'packages/a',
'packages/b',
'packages/c',
const TSCONFIG_LINT_FILE_NAME = '.tsconfig-lint.json';
const files = process.argv.slice(2);
Promise.all(
packages.map((package) => {
const absolutePackagePath = path.resolve(package);
const includedFiles = files.filter((file) => file.startsWith(absolutePackagePath));
if (includedFiles.length) {
const tsconfig = {
extends: './tsconfig.json',
include: [...includedFiles, '**/*.d.ts'],
const tsconfigLintPath = `${package}/${TSCONFIG_LINT_FILE_NAME}`;
fs.writeFileSync(tsconfigLintPath, JSON.stringify(tsconfig, null, 2));
return spawn.sync(path.resolve('./node_modules/.bin/tsc'), [
'--project',
tsconfigLintPath,
'--noEmit',
'--skipLibCheck',
return undefined;
.then((children) => Promise.all(children.filter((child) => child && child.status !== 0)))
.then((children) => Promise.all(children.map((child) => child.stdout)))
.then((errors) => {
if (errors.length) {
throw errors;
return errors;
暴走的楼房 · 网易市值反超美团,丁磊“闷声发大财” | 投中网 1 月前 |