即使声明了 Typescript 也找不到属性

Posted

技术标签:

【中文标题】即使声明了 Typescript 也找不到属性【英文标题】:Typescript can't find property even though declared 【发布时间】:2020-06-09 14:13:06 【问题描述】:

我正在尝试修改我正在使用的包的类型声明,因为这些类型已过时。我可以很好地调整大多数东西,但有一个错误我似乎无法修复,那就是从函数返回的接口属性。

这是一个代码示例。我已经删除了我很确定与问题无关的代码,以使其更容易阅读。如果您觉得缺少一些可能有助于理解问题的内容,请告诉我。

declare namespace renderContent 
  type renderContentCallback = (
    eventOrImage: Event | htmlCanvasElement | HTMLImageElement,
    data?: MetaData
  ) => void;

  interface ImageHead 
    imageHead?: ArrayBuffer | Uint8Array;
  

  interface MetaData extends ImageHead 
    //...
  

  interface PromiseData extends MetaData 
    image: HTMLCanvasElement | HTMLImageElement;
  

  interface BasicOptions 
    //...
  

  type renderContentOptions = BasicOptions


interface renderContent 
  (
    file: File | Blob | string,
    /* If options are defined instead of a callback function, the next argument will be skipped and the function will return a promise */
    callbackOrOption?: renderContent.renderContentCallback | renderContent.renderContentOptions,
    options?: renderContent.renderContentOptions
  ): HTMLImageElement | FileReader | Promise<renderContent.PromiseData> | false;


declare const renderContent: renderContent;

export = renderContent;

当我像这样在我的代码中使用它时:

const  image  = await renderContent(file, options);

我收到一条错误消息:

类型“假”上不存在属性“图像”| HTMLImageElement | 文件阅读器 | PromiseData'

对我来说,它似乎在 PromiseData 接口中明确定义,并在错误消息中列出。那我错过了什么?

【问题讨论】:

【参考方案1】:

问题是,打字稿不能确定renderContent 返回的类型是Promise&lt;renderContent.PromiseData&gt;。实际上,对于 typescript,类型也可以是 FileReaderHtMLImageElement...

这些类型没有密钥 image,这就是您收到此错误的原因。

我想你认为使用关键字await 会使打字稿猜测Promise&lt;renderContent.PromiseData&gt; 是正确的返回类型,但不幸的是不是。


为了告诉 typescript 你在等什么,使用关键字as,比如:

playground

const  image  = await (renderContent(_) as Promise<renderContent.PromiseData>);

关于&解决方案:

它可能有效,但有副作用。例如:

如果你使用这样的功能:

 const data = renderContent(false as unknown as File);

Typescript 将允许您调用data.readAsArrayBufferdata.height 一样多,这是错误的。因为renderContent 要么返回HTMLCanvasElement,要么返回HTMLImageElement


一个新的解决方案!有一点返工:​​3>

综合考虑,更好的解决方案是准确描述renderContent 调用场景的样子:

type possibilityA = (
    file: File | Blob | string,
    options: renderContent.renderContentOptions
) => Promise<renderContent.PromiseData>;

type possibilityB = (
    file: File | Blob | string,
    callback: renderContent.renderContentCallback,
) => HTMLImageElement | FileReader | false;

type possibilityC = (
    file: File | Blob | string,
    callback: renderContent.renderContentCallback,
    options: renderContent.renderContentOptions
) => HTMLImageElement | FileReader | false;

type renderContent = possibilityA & possibilityB & possibilityC;

declare const renderContent: renderContent;

(async() => 
  const data = await renderContent('foo',   );
)();

playground

在此解决方案中,typescript 将根据您提供的参数选择适当的重载,该参数将相应地定义 data 的类型。

【讨论】:

谢谢 Grégory,这似乎可行,我能够让它与 const image = await (renderContent(file as File, option) as Promise&lt;renderContent.PromiseData&gt;); 一起工作但我也刚刚发现我可以通过更改预期来解决问题,而无需修改函数返回HTMLImageElement &amp; FileReader &amp; Promise&lt;renderContent.PromiseData&gt; &amp; false。可能有不推荐方法的原因吗? @EinarÓlafsson 我已经编辑了我的帖子,其中包含对您的回答以及处理所有案件的另一个解决方案! (良好的自动完成和类型检查) 该解决方案效果很好,非常感谢您对实现的解释,非常有帮助!

以上是关于即使声明了 Typescript 也找不到属性的主要内容,如果未能解决你的问题,请参考以下文章

即使 tsc 成功解决它,也找不到 Typescript 模块

为啥即使安装了 FBX 模块也找不到?

即使在调试中,React Native 测试库也找不到文本

即使启用了自动绑定,也找不到程序集

为啥即使创建了对象,django 也找不到与查询匹配的任何对象

即使明确提供了模块路径,Eclipse 也找不到模块