属性 'foo' 在使用 new Proxy({}) 时在类型“{}”上不存在,.....)

Property 'foo' does not exist on type '{}' when using new Proxy({}), .....)

我没有使用打字稿(而且,现在我不打算使用)但是 VSCode 的默认设置似乎已经为我进行了一些检查。这有点方便,有点痛苦。我想暂时坚持下去。

导致此问题的代码是:

  let {
    localApiVersion, localDate, remoteVersion, remoteDate,
  } = new Proxy({}, { get: () => null });

这是我从我的 中拿走的。我这样做是因为我不想 let localApiVersion = null 四次。

但是 VSCode 给我这个错误:

Property 'localApiVersion' does not exist on type '{}'.ts(2339)

检查(我认为)是因为我的 jscongig.json 看起来像这样:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es2019",
        "checkJs": true
    },
    "exclude": [
        "node_modules",
        "**/node_modules/*"
    ]
}

我知道我可以在那行上方写 // @ts-ignore,但不想养成那个习惯。

有没有办法,不删除检查(或向项目添加打字稿),通知VSCode这些都可以?

您在 JavaScript 代码上遇到 TypeScript 错误似乎很令人惊讶,但您可以通过 JSDoc 注释(请参阅 here, here, and here)提供类型信息,这些注释只是注释,因此它们不会在 JavaScript 环境中 运行 代码之前不需要使用 TypeScript 编译器。

话虽如此,我就是无法让它与 JSDoc 注释一起使用。我希望这会起作用,因为 third link above 说你可以这样进行类型断言:

// @ts-check

/**
 * @typedef {Object} Stuff - comment here
 * @property {any} localApiVersion - comment here
 * @property {any} localDate - comment here
 * @property {any} remoteVersion - comment here
 * @property {any} remoteDate - comment here
 */

let {
    localApiVersion, localDate, remoteVersion, remoteDate,
} = new Proxy(/** @type {Stuff} */ {}, { get: () => null });;

但这不起作用。 :-(

就其价值而言,这在 TypeScript 本身中很容易:

interface Stuff {
    localApiVersion: any;
    localDate: any;
    remoteVersion: any;
    remoteDate: any;
}

let {
    localApiVersion, localDate, remoteVersion, remoteDate,
} = new Proxy({} as Stuff, { get: () => null });
//               ^^^^^^^^−−−−−−− type assertion
// I normally avoid type assertions, but this use of the Proxy with get
// trap is a very special case.

TypeScript playground 上的示例。)

我希望 JSDoc 注释可以实现,因为我知道人们使用 TypeScript 类型检查方式,但是,好吧,我只使用 TypeScript 并且还没有能够找出 JSDoc 等价物。

{}类型来自ProxyConstructor中的T extends object约束;在没有显式类型的情况下,T 被解析为一个空对象,或者 {}.

但是,{} 不符合要求,因为它没有任何属性,而您的代码要求它具有 localApiVersionlocalDate 等。是的, JavaScript 知道这些属性(或者更确切地说它不关心),但是 TypeScript 不知道它们,并且它无法与运行时代码通信。

解决方案是至少对这张图片中的某些内容进行类型转换,以便 TypeScript 可以推断出正确的类型。在 .ts 文件中,这是微不足道的。但是,在 .js 文件中,可以这样做:

// @ts-check

/** @type {Record<string, unknown>} */
const target = {};

let { foo, bar, baz } = new Proxy(target, { get: () => null });

这是对我有用的(也请为其他答案投票,它们对我到达这里很有帮助):

  let {
    localApiVersion, localDate, remoteVersion, remoteDate,
  } = /** @type {Object.<string, (null|string)>} */ (new Proxy({}, { get: () => null }));

请注意 @type 注释位于 new 之前,并且整个构造函数部分都包含在括号中。我使用 (null|string) 而不是 unknown a) 因为我知道它将被重新分配给一个字符串 b) 所以我仍然得到 some 类型检查,即使在重新分配之前你可能会犯类型错误。我可能会将其切换为 null,并且在显式更改类型时使用此类内容:@type {string} (localApiVersion).

这是 VSCode 中的工具提示:

使用 typedef 也可以:

  /**
   * @typedef {Object.<string, (null|string)>} InitProxy
   */

  let {
    localApiVersion, localDate, remoteVersion, remoteDate,
  } = /** @type {InitProxy} */ (new Proxy({}, { get: () => null }));

但这已经到了我试图避免的冗长程度。