我正在尝试将Typescript项目配置为具有以下目录结构:
src/
├── client/
│ └── tsconfig.json
│
├── server/
│ └── tsconfig.json
│
├── shared/
│ ├── utils/
│ │ └── type-utils.d.ts
│ │
│ └── tsconfig.json
│
└── tsconfig-base.json
client/tsconfig.json
,server/tsconfig.json
和shared/tsconfig.json
分别具有"extends": "../tsconfig-base.json"
client/tsconfig.json
和server/tsconfig.json
都具有"references": [{ "path": "../shared" }]
shared/utils/type-utils.d.ts
不是模块,而是包含环境类型声明,例如Id
和CouldBeNull
,以及Array
的声明合并(定义flatMap
方法。
这样的想法是tsconfig-base.json
可以包含很多通用设置,单个tsconfig.json
可以定义与该子项目相关的设置(例如,React for client/tsconfig.json
,Node for { {1}}和server/tsconfig.json
将在shared/
和client/
之间共享。
问题在于,server/
或shared/utils/type-utils.ts
看不到环境声明和声明合并client/
,而server/
则看不到。这会导致错误,例如shared/
产生
tsc -b client --verbose
隐式$ tsc -b client --verbose
15:31:41 - Projects in this build:
* shared/tsconfig.json
* client/tsconfig.json
15:31:41 - Project 'shared/tsconfig.json' is up to date because newest input 'shared/formatting/numbers.ts' is older than oldest output 'shared/formatting/numbers.js.map'
15:31:41 - Project 'client/tsconfig.json' is out of date because output file 'client/client/index.js' does not exist
15:31:41 - Building project 'C:/Users/KRyan/Web/5heet/client/tsconfig.json'...
client/index.tsx(32,29): error TS7006: Parameter 'skill' implicitly has an 'any' type.
client/index.tsx(80,37): error TS2339: Property 'flatMap' does not exist on type 'Ability[]'.
client/index.tsx(80,45): error TS7006: Parameter 'ability' implicitly has an 'any' type.
client/index.tsx(88,16): error TS7006: Parameter 'one' implicitly has an 'any' type.
client/index.tsx(88,21): error TS7006: Parameter 'another' implicitly has an 'any' type.
client/index.tsx(151,32): error TS7031: Binding element 'id' implicitly has an 'any' type.
client/parts/editing.tsx(31,60): error TS2339: Property 'oneOperand' does not exist on type 'never'.
client/parts/editing.tsx(31,81): error TS2339: Property 'operator' does not exist on type 'never'.
client/parts/editing.tsx(31,108): error TS2339: Property 'anotherOperand' does not exist on type 'never'.
client/parts/portal.tsx(55,61): error TS2304: Cannot find name 'Omit'.
shared/ability.d.ts(2,33): error TS2304: Cannot find name 'Id'.
shared/ability.d.ts(8,36): error TS2304: Cannot find name 'Id'.
shared/ability.d.ts(12,37): error TS2304: Cannot find name 'Id'.
shared/character.d.ts(3,35): error TS2304: Cannot find name 'Id'.
shared/expression.d.ts(7,35): error TS2304: Cannot find name 'Id'.
shared/expression.d.ts(30,38): error TS2304: Cannot find name 'ElementOf'.
shared/expression.d.ts(33,118): error TS2304: Cannot find name 'Id'.
shared/formatting/numbers.d.ts(1,41): error TS2304: Cannot find name 'Id'.
shared/skill.d.ts(3,31): error TS2304: Cannot find name 'Id'.
shared/utils/basic.d.ts(5,46): error TS2304: Cannot find name 'CouldBeNull'.
类型是由于无法找到输出后半部分列出的各种名称而直接导致的。
出于完整性考虑,完整文件:
any
:
shared/utils/type-utils.d.ts
type PropsOf<T> = T[keyof T];
type ElementOf<T> = T extends (infer E)[] ? E : T;
type Subtract<T, U> = Pick<T, Exclude<keyof T, keyof U>>;
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type CouldBeNull<T> = null extends T ? unknown : never;
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends Array<infer U>
? Array<DeepPartial<U>>
: T[P] extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: DeepPartial<T[P]>
};
declare class Tagged<Tag> {
private 'is tagged as': [Tag];
private dummy(): Tag;
}
type Id<Tag> = string & Tagged<Tag>;
interface Array<T> {
/**
* Calls a defined callback function on each element of an array. Then, flattens the result into
* a new array.
* This is identical to a map followed by a flatten of depth 1.
*
* @param callback A function that accepts up to three arguments. The flatMap method calls the
* callback function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callback function. If
* thisArg is omitted, undefined is used as the this value.
*/
flatMap<U, This = undefined>(
callback: (this: This, value: T, index: number, array: T[]) => U | U[],
thisArg?: This,
): U[];
}
:
tsconfig-base.json
{
"compileOnSave": true,
"compilerOptions": {
"target": "es2018",
"baseUrl": ".",
"module": "amd",
"moduleResolution": "classic",
"paths": {
"csstype": [
"node_modules/csstype/index"
],
},
"composite": true,
"declaration": true,
"declarationMap": true,
"noEmitOnError": true,
"strictNullChecks": true,
"allowJs": false,
"allowUnusedLabels": false,
"noImplicitAny": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noStrictGenericChecks": true,
"noUnusedLocals": true,
"noErrorTruncation": true,
"allowUnreachableCode": false,
"forceConsistentCasingInFileNames": false,
"preserveConstEnums": true,
"sourceMap": true
}
}
:
client/tsconfig.json
{
"extends": "../tsconfig-base.json",
"include": [
"**/*.ts"
],
"outDir": "../../built/client",
"compilerOptions": {
"rootDir": "..",
"jsx": "react",
"types": [
"react",
"react-dom"
]
},
"references": [
{
"path": "../shared"
}
],
"watch": true
}
:
server/tsconfig.json
{
"extends": "../tsconfig-base.json",
"include": [
"**/*.ts"
],
"outDir": "../../built/server",
"compilerOptions": {
"rootDir": "..",
"module": "commonjs",
"types": [
"node",
"mime-types"
]
},
"references": [
{
"path": "../shared"
}
]
}
:
shared/tsconfig.json
答案 0 :(得分:0)
想出了 a 解决方案,尽管我对此并不感到困惑:
client/tsconfig.json
:
{
"extends": "../tsconfig-base.json",
"include": [
"**/*.ts",
"**/*.tsx",
"../shared/utils/type-utils.d.ts"
],
"outDir": "../built/client",
"compilerOptions": {
"baseUrl": "..",
"rootDir": "..",
"jsx": "react",
"types": [
"react",
"react-dom"
]
},
"references": [
{
"path": "../shared"
}
],
"watch": true
}
请注意../shared/utils/type-utils.d.ts
部分中的include
。这样就解决了问题。
我对这种解决方案并不陌生,因为它意味着在shared/
中明确列出某些内容,而不是作为项目参考的结果而将其包括在内。我对于必须为要添加tsconfig.json
的每个新.d.ts
文件必须手动更新shared/
的想法感到不满意。但这是 的答案,因为该项目可以构建,而且我并不是很可能 向该项目添加更多自己的.d.ts
文件,因此我对此项目的关注可能是哲学/理论上的。