错误 TS7053:元素隐式具有'any'类型,因为表达式 + 其他 TS 错误



我们在CI工具(VSC/Github(中自动检查了更漂亮的/lint/typescript错误。

最近,dependenabot的一到两个更新已开始在多个不同的位置和不同的ts文件中使ts脚本失败。由于我不是一个ts人,而且我已经从别人那里接手了这件事,我想得到一些帮助来理解。我已经查看了其他各种帖子中的相同错误,但仍然不知道在我的例子中应该更改什么,我不想更改错误的内容。

  1. 错误:
Error: salesforce-utils/src/bin/cancel-deploy.ts(19,29): error TS7053: Element implicitly has an 'any' type because expression of type '"save-progress-file"' can't be used to index type '{ [x: string]: unknown; "save-progress-file": string; _: (string | number)[]; $0: string; } | Promise<{ [x: string]: unknown; "save-progress-file": string; _: (string | number)[]; $0: string; }>'.
Property 'save-progress-file' does not exist on type '{ [x: string]: unknown; "save-progress-file": string; _: (string | number)[]; $0: string; } | Promise<{ [x: string]: unknown; "save-progress-file": string; _: (string | number)[]; $0: string; }>'.

文件cancel-deploy.ts,现在是第19行,它在抱怨this.saveProgressFile = argv["save-progress-file"];:

import yargs = require("yargs");
import { State } from "../deploy";
class Config {
saveProgressFile: string;
constructor() {
const argv = yargs
.scriptName("cancel-deploy")
.describe(
"save-progress-file",
"Save a file with the progress that can be used to resume. Default: [cluster-developer-name].deploy-log.json."
)
.alias("save-progress-file", "s")
.string("save-progress-file")
.demandOption("save-progress-file").argv;
this.saveProgressFile = argv["save-progress-file"];
}
...etc
  1. 相同的错误,不同的文件,其中该代码段中的最后一行都有一个错误:
constructor() {
const argv = yargs
.scriptName("deploy")
.describe("cluster-config-file", "The file configuring the SF2SF sync.")
.alias("cluster-config-file", "f")
.string("cluster-config-file")
.required("cluster-config-file")
.array("cluster-config-file")
.describe("validate", "Only do the validate part of the deploy")
.alias("validate", "v")
.boolean("validate")
.default("validate", false)
.describe("quick", "Don't wait for job to complete")
.alias("quick", "q")
.boolean("quick")
.default("quick", false)
.describe("resume", "Resume the deploy described in the file")
.alias("resume", "r")
.string("resume")
.string("test-level")
.alias("test-level", "l")
.describe("test-level", "Passed through to the sfdx validate command")
.default("test-level", "RunLocalTests")
.describe(
"save-progress-file",
"Save a file with the progress that can be used to resume. Default: [cluster-developer-name].deploy-log.json."
)
.alias("save-progress-file", "s")
.string("save-progress-file")
.describe("skip-validation", "Skip the validation process, just deploy")
.boolean("skip-validation")
.default("skip-validation", false).argv;
this.clusterConfigFiles = argv["cluster-config-file"];
this.validateOnly = argv["validate"];
this.quick = argv["quick"];
this.resume = argv["resume"];
this.testLevel = argv["test-level"];
this.saveProgressFile = argv["save-progress-file"];
this.skipValidation = argv["skip-validation"];
}

还有几个ts文件,它们具有相同的构造函数设置和args,然后分配它们。

我该如何修复这些?任何ts更新现在都无法通过我们的CI过程,因为脚本不再通过检查。我可以关闭类型检查,但更愿意修复文件(如果这是更好的解决方案(。

  1. 我有另一个可靠更新,它也引发了其他错误:

Error: salesforce-utils/src/bin/subscribed-fields.ts(190,11): error TS2349: This expression is not callable

Error: salesforce-utils/src/bin/subscribed-fields.ts(197,22): error TS2571: Object is of type 'unknown'.

Error: salesforce-utils/src/bin/subscribed-fields.ts(207,11): error TS2345: Argument of type 'unknown' is not assignable to parameter of type 'Connection'.

以下是ts文件中出现错误的部分:

(async (): Promise<void> => {
const argv = new Config();
const { clusterConfigFile, concurrency } = argv;
const clusterConfig = await SyndexClusterConfig.fromPath(clusterConfigFile);
const browser = await launch();
const connections = flatten(
await pAll(
clusterConfig.usernames.map(
(username) => (): Promise<Connection[]> =>
loginAndGetConnections(browser, username)
),
{ concurrency }
)
).filter((conn) => conn.isActive);
const differences: SubscribedFieldUpdate[] = [];
await pAll(
connections.map(
(connection) => (): Promise<void> =>
checkDifferencesForConnectionSafely(
argv,
browser,
connection,
differences
)
),
{ concurrency }
);
const result = differences.map(
({ connection, connectionObject, connectionField, newValue }) => ({
username: connection.username,
connection: connection.name,
object: connectionObject.name,
field: connectionField.name,
oldValue: (connectionField.value && connectionField.value.name) || "",
newValue: (newValue && newValue.name) || ""
})
);
console.log(JSON.stringify(result, null, "  "));
await browser.close();
})();

1&2:

如果你仔细查看错误消息(并将其格式化以使其清晰可见(:

'"save-progress-file"' can't be used to index type
'{
[x: string]: unknown;
"save-progress-file": string;
_: (string | number)[];
$0: string;
}
| Promise<{
[x: string]: unknown;
"save-progress-file": string;
_: (string | number)[];
$0: string;
}>'.

所以typescript认为argv可能是一个对象或一个承诺。如果这是一个承诺,那么thePromise["save-progress-file"]就会失败。

事实上,如果你把鼠标悬停在yargs.argv上,你会看到这种类型:

const argv = yargs.argv // hover this to get the below type
(property) yargs.Argv<{}>.argv: {
[x: string]: unknown;
_: (string | number)[];
$0: string;
} | Promise<{
[x: string]: unknown;
_: (string | number)[];
$0: string;
}>

因此,要解决这个问题,您需要处理argv是一个承诺的情况。你可以通过await来实现。如果值是promise,它会等待,如果不是,它会立即进行。

const argv = await yargs.argv // hover this const to get the below type
{
[x: string]: unknown;
_: (string | number)[];
$0: string;
} | {
[x: string]: unknown;
_: (string | number)[];
$0: string;
}

这里的报道类型有点奇怪,但正如你所看到的,没有更多的承诺!

但是,这些都在构造函数中,类构造函数不能是异步的。这意味着您必须对代码进行大量重构,以使其成为async

或者,如果由于您使用API的方式,您知道这永远不会是承诺,那么您可以尝试检测它是否是承诺,然后抛出错误。然后Typescript应该能够继续假设它不是一个承诺。

为什么yargs.argv可以成为一个承诺,以及它希望你如何处理,我不知道。您应该查阅该库的文档。


我不打算深究#3,因为这已经是一篇大文章了。但我建议你也要经历同样的过程。仔细检查错误,复制/粘贴,格式化,直到可以很容易地推理为止。将鼠标悬停在编辑器中的变量上,并记下类型。然后最终修复您对有问题的API的使用,使其正确无误。

相关内容

最新更新