【问题标题】:Project references in tsconfig and ambient declarationstsconfig 和环境声明中的项目引用
【发布时间】:2019-05-01 18:47:37
【问题描述】:

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

src/
├── client/
│   └── tsconfig.json
│
├── server/
│   └── tsconfig.json
│
├── shared/
│   ├── utils/
│   │   └── type-utils.d.ts
│   │
│   └── tsconfig.json
│
└── tsconfig-base.json
  • client/tsconfig.jsonserver/tsconfig.jsonshared/tsconfig.json 各有 "extends": "../tsconfig-base.json"

  • client/tsconfig.jsonserver/tsconfig.json 都有 "references": [{ "path": "../shared" }]

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

这个想法是 tsconfig-base.json 可以包含许多通用设置,单个 tsconfig.jsons 可以定义与该子项目相关的设置(例如,client/tsconfig.json 的 React,server/tsconfig.json 的 Node)和 @ 987654338@ 将在client/server/ 之间共享。

问题在于client/server/ 看不到环境声明和声明合并shared/utils/type-utils.ts,而只有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:

{
    "extends": "../../tsconfig-base.json",
    "include": [
        "**/*.ts"
    ],
    "outDir": "built/shared",
    "compilerOptions": {
        "module": "amd",
        "types": []
    }
}

【问题讨论】:

  • @E_net4 友善而热情 为什么四个空格缩进比&lt;pre&gt; 标签更可取?只是想了解这个系统,我以前从未注意到有什么不同。
  • &lt;pre&gt; 标签不提供语法高亮,这与四空格缩进不同。这也是一种更自然的(Markdown)格式化代码的方式。

标签: typescript build dependencies tsconfig


【解决方案1】:

想出了一个解决方案,虽然我对此并不疯狂:

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
}

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

我对这个解决方案并不感兴趣,因为它意味着在 shared/ 中明确列出某些内容,而不是作为项目引用的结果而包含在内。想到我必须为每个要添加shared/ 的新.d.ts 文件手动更新我的tsconfig.jsons,我感到很不高兴。但这是一个的答案,因为项目正在构建,我不太可能可能将更多我自己的.d.ts文件添加到项目中,所以我担心可能是这个项目的哲学/理论。

【讨论】:

  • 您好,感谢您的解决方案。帮助很大。它已经很老了,但是如果它仍然有用,您可以将“../shared/utils/type-utils.d.ts”替换为“../**/*.d.ts”,这更好一些,适用于我。
  • @AlonBar 老实说,我不记得我是否真的尝试过,但如果我不这样做,那我就太愚蠢了——这似乎是一件很明显的事情。但我很高兴这里有更好的解决方案。
猜你喜欢
  • 1970-01-01
  • 2012-11-08
  • 2021-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-30
  • 2016-05-14
  • 1970-01-01
相关资源
最近更新 更多