即使声明了 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<renderContent.PromiseData>
。实际上,对于 typescript,类型也可以是 FileReader
或 HtMLImageElement
...
这些类型没有密钥 image
,这就是您收到此错误的原因。
我想你认为使用关键字await
会使打字稿猜测Promise<renderContent.PromiseData>
是正确的返回类型,但不幸的是不是。
为了告诉 typescript 你在等什么,使用关键字as
,比如:
playground
const image = await (renderContent(_) as Promise<renderContent.PromiseData>);
关于&解决方案:
它可能有效,但有副作用。例如:
如果你使用这样的功能:
const data = renderContent(false as unknown as File);
Typescript 将允许您调用data.readAsArrayBuffer
和data.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<renderContent.PromiseData>);
一起工作但我也刚刚发现我可以通过更改预期来解决问题,而无需修改函数返回HTMLImageElement & FileReader & Promise<renderContent.PromiseData> & false
。可能有不推荐方法的原因吗?
@EinarÓlafsson 我已经编辑了我的帖子,其中包含对您的回答以及处理所有案件的另一个解决方案! (良好的自动完成和类型检查)
该解决方案效果很好,非常感谢您对实现的解释,非常有帮助!以上是关于即使声明了 Typescript 也找不到属性的主要内容,如果未能解决你的问题,请参考以下文章
即使 tsc 成功解决它,也找不到 Typescript 模块