tsconfig 和环境声明中的项目引用

KRy*_*yan 8 dependencies build typescript tsconfig

我正在尝试将我的 Typescript 项目配置为具有以下目录结构:

\n\n
src/\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 client/\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n\xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 server/\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n\xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 shared/\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 utils/\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 type-utils.d.ts\n\xe2\x94\x82   \xe2\x94\x82\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n\xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig-base.json\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  • client/tsconfig.json, server/tsconfig.json, 且shared/tsconfig.json各有"extends": "../tsconfig-base.json"

  • \n
  • client/tsconfig.json并且server/tsconfig.json两者都有"references": [{ "path": "../shared" }]

  • \n
  • shared/utils/type-utils.d.ts不是模块,而是包含环境类型声明,例如IdCouldBeNull,以及声明合并 for Array(定义flatMap方法)。

  • \n
\n\n

这个想法是,tsconfig-base.json可以包含许多通用设置,个人tsconfig.json可以定义与该子项目相关的设置(例如 React for client/tsconfig.json、 Node for server/tsconfig.json),并且shared/可以在client/和 之间共享server/

\n\n

问题是环境声明和声明合并shared/utils/type-utils.ts不能被client/or看到server/,而只能被 看到shared/。这会导致错误,例如tsc -b client --verbose产生

\n\n
$ tsc -b client --verbose\n15:31:41 - Projects in this build:\n    * shared/tsconfig.json\n    * client/tsconfig.json\n\n15: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\'\n\n15:31:41 - Project \'client/tsconfig.json\' is out of date because output file \'client/client/index.js\' does not exist\n\n15:31:41 - Building project \'C:/Users/KRyan/Web/5heet/client/tsconfig.json\'...\n\nclient/index.tsx(32,29): error TS7006: Parameter \'skill\' implicitly has an \'any\' type.\nclient/index.tsx(80,37): error TS2339: Property \'flatMap\' does not exist on type \'Ability[]\'.\nclient/index.tsx(80,45): error TS7006: Parameter \'ability\' implicitly has an \'any\' type.\nclient/index.tsx(88,16): error TS7006: Parameter \'one\' implicitly has an \'any\' type.\nclient/index.tsx(88,21): error TS7006: Parameter \'another\' implicitly has an \'any\' type.\nclient/index.tsx(151,32): error TS7031: Binding element \'id\' implicitly has an \'any\' type.\nclient/parts/editing.tsx(31,60): error TS2339: Property \'oneOperand\' does not exist on type \'never\'.\nclient/parts/editing.tsx(31,81): error TS2339: Property \'operator\' does not exist on type \'never\'.\nclient/parts/editing.tsx(31,108): error TS2339: Property \'anotherOperand\' does not exist on type \'never\'.\nclient/parts/portal.tsx(55,61): error TS2304: Cannot find name \'Omit\'.\nshared/ability.d.ts(2,33): error TS2304: Cannot find name \'Id\'.\nshared/ability.d.ts(8,36): error TS2304: Cannot find name \'Id\'.\nshared/ability.d.ts(12,37): error TS2304: Cannot find name \'Id\'.\nshared/character.d.ts(3,35): error TS2304: Cannot find name \'Id\'.\nshared/expression.d.ts(7,35): error TS2304: Cannot find name \'Id\'.\nshared/expression.d.ts(30,38): error TS2304: Cannot find name \'ElementOf\'.\nshared/expression.d.ts(33,118): error TS2304: Cannot find name \'Id\'.\nshared/formatting/numbers.d.ts(1,41): error TS2304: Cannot find name \'Id\'.\nshared/skill.d.ts(3,31): error TS2304: Cannot find name \'Id\'.\nshared/utils/basic.d.ts(5,46): error TS2304: Cannot find name \'CouldBeNull\'.\n
Run Code Online (Sandbox Code Playgroud)\n\n

隐式any类型是由于无法找到输出后半部分列出的各种名称直接导致的。

\n\n

并且,为了完整性\xe2\x80\x99s,完整文件:

\n\n

shared/utils/type-utils.d.ts:

\n\n
type PropsOf<T> = T[keyof T];\ntype ElementOf<T> = T extends (infer E)[] ? E : T;\ntype Subtract<T, U> = Pick<T, Exclude<keyof T, keyof U>>;\ntype Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;\ntype CouldBeNull<T> = null extends T ? unknown : never;\n\ntype DeepPartial<T> = {\n    [P in keyof T]?: T[P] extends Array<infer U>\n    ? Array<DeepPartial<U>>\n    : T[P] extends ReadonlyArray<infer U>\n    ? ReadonlyArray<DeepPartial<U>>\n    : DeepPartial<T[P]>\n};\n\ndeclare class Tagged<Tag> {\n    private \'is tagged as\': [Tag];\n    private dummy(): Tag;\n}\ntype Id<Tag> = string & Tagged<Tag>;\n\ninterface Array<T> {\n    /**\n     * Calls a defined callback function on each element of an array. Then, flattens the result into\n     * a new array.\n     * This is identical to a map followed by a flatten of depth 1.\n     *\n     * @param callback A function that accepts up to three arguments. The flatMap method calls the\n     * callback function one time for each element in the array.\n     * @param thisArg An object to which the this keyword can refer in the callback function. If\n     * thisArg is omitted, undefined is used as the this value.\n     */\n    flatMap<U, This = undefined>(\n        callback: (this: This, value: T, index: number, array: T[]) => U | U[],\n        thisArg?: This,\n    ): U[];\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

tsconfig-base.json:

\n\n
{\n    "compileOnSave": true,\n    "compilerOptions": {\n        "target": "es2018",\n        "baseUrl": ".",\n        "module": "amd",\n        "moduleResolution": "classic",\n        "paths": {\n            "csstype": [\n                "node_modules/csstype/index"\n            ],\n        },\n        "composite": true,\n        "declaration": true,\n        "declarationMap": true,\n        "noEmitOnError": true,\n        "strictNullChecks": true,\n        "allowJs": false,\n        "allowUnusedLabels": false,\n        "noImplicitAny": true,\n        "noImplicitThis": true,\n        "noImplicitReturns": true,\n        "noUnusedParameters": true,\n        "noFallthroughCasesInSwitch": true,\n        "noStrictGenericChecks": true,\n        "noUnusedLocals": true,\n        "noErrorTruncation": true,\n        "allowUnreachableCode": false,\n        "forceConsistentCasingInFileNames": false,\n        "preserveConstEnums": true,\n        "sourceMap": true\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

client/tsconfig.json:

\n\n
{\n    "extends": "../tsconfig-base.json",\n    "include": [\n        "**/*.ts"\n    ],\n    "outDir": "../../built/client",\n    "compilerOptions": {\n        "rootDir": "..",\n        "jsx": "react",\n        "types": [\n            "react",\n            "react-dom"\n        ]\n    },\n    "references": [\n        {\n            "path": "../shared"\n        }\n    ],\n    "watch": true\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

server/tsconfig.json:

\n\n
{\n    "extends": "../tsconfig-base.json",\n    "include": [\n        "**/*.ts"\n    ],\n    "outDir": "../../built/server",\n    "compilerOptions": {\n        "rootDir": "..",\n        "module": "commonjs",\n        "types": [\n            "node",\n            "mime-types"\n        ]\n    },\n    "references": [\n        {\n            "path": "../shared"\n        }\n    ]\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

shared/tsconfig.json:

\n\n
{\n    "extends": "../../tsconfig-base.json",\n    "include": [\n        "**/*.ts"\n    ],\n    "outDir": "built/shared",\n    "compilerOptions": {\n        "module": "amd",\n        "types": []\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

KRy*_*yan 6

找到了一个解决方案,尽管我\xe2\x80\x99m对此并不狂热:

\n\n

client/tsconfig.json:

\n\n
{\n    "extends": "../tsconfig-base.json",\n    "include": [\n        "**/*.ts",\n        "**/*.tsx",\n        "../shared/utils/type-utils.d.ts"\n    ],\n    "outDir": "../built/client",\n    "compilerOptions": {\n        "baseUrl": "..",\n        "rootDir": "..",\n        "jsx": "react",\n        "types": [\n            "react",\n            "react-dom"\n        ]\n    },\n    "references": [\n        {\n            "path": "../shared"\n        }\n    ],\n    "watch": true\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意部分../shared/utils/type-utils.d.ts中的include。这解决了问题。

\n\n

I\xe2\x80\x99m 对此解决方案并不感兴趣,因为它意味着显式列出某些内容shared/,而不是仅仅将其作为项目引用的结果包含在内。我对必须tsconfig.json为每个.d.ts要添加的新文件手动更新我的想法感到不高兴shared/。但这是一个答案,因为项目会构建,并且 I\xe2\x80\x99m 不太可能.d.ts向项目添加更多我自己的文件,所以我的担忧可能是这个项目的哲学/理论。

\n