打字稿:问题类型系统(TypeScript: problems with type system)

2019-08-03 10:40发布

我只是在2012年的VisualStudio测试打字稿,并与它的类型系统出了问题。 我的HTML网站有id为“mycanvas”在画布标记。 我想得出这样的画布上的矩形。 下面的代码

var canvas = document.getElementById("mycanvas");
var ctx: CanvasRenderingContext2D = canvas.getContext("2d");
ctx.fillStyle = "#00FF00";
ctx.fillRect(0, 0, 100, 100);

不幸的是VisualStudio的抱怨

财产“的getContext”确实对类型“HTML元素”的值不存在

它标志着第二行为错误。 我认为这将是仅仅是一个警告,但代码不编译。 VisualStudio中说,

有生成错误。 你想继续和运行上次成功构建?

我不喜欢这样的错误的。 为什么没有动态方法调用? 所有的方法后的getContext肯定存在我的画布元素。 不过,我认为这个问题很容易解决。 我只是增加了画布类型annotiation:

var canvas : HTMLCanvasElement = document.getElementById("mycanvas");
var ctx: CanvasRenderingContext2D = canvas.getContext("2d");
ctx.fillStyle = "#00FF00";
ctx.fillRect(0, 0, 100, 100);

但类型系统还不满意。 这里是新的错误消息,这一次在第一行:

无法将“HTML元素”到“HTMLCanvasElement”:从类型类型“HTML元素”缺少财产“toDataURL“HTMLCanvasElement”

好吧,我全力以赴为静态类型,但是这使语言无法使用。 是什么类型的系统要我怎么做?

更新:

打字稿也的确动态调用不支​​持,我的问题可以用类型转换来解决。 我的问题基本上是这样一个的副本打字稿:铸造HTML元素

Answer 1:

var canvas = <HTMLCanvasElement> document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");

或使用动态查找与any类型(无类型检查):

var canvas : any = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");

你可以看一下不同类型的lib.d.ts 。



Answer 2:

看来这是打字稿的0.9版本被纠正: http://blogs.msdn.com/b/typescript/archive/2013/03/25/working-on-typescript-0-9-generics-overload-关于常数和编译器,performance.aspx参见在canvas标签明确表示“对常量超载”一节。



Answer 3:

我有同样的问题,但随着SVGSVGElement而不是HTMLCanvasElement。 铸造到SVGSVGElement给了一个编译时错误:

var mySvg = <SVGSVGElement>document.getElementById('mySvg');

无法将“HTML元素”到“SVGSVGElement”:
类型“HTMLElement的”缺少从类型“SVGSVGElement”属性的“width”。
类型“SVGSVGElement”缺少财产型“OnMouseLeave在“HTML元素”。

如果第一铸造“任意”固定它:

var mySvg = <SVGSVGElement><any>document.getElementById('mySvg');

或这种方式(它具有相同的效果)

var mySvg: SVGSVGElement = <any>document.getElementById('mySvg');

现在mySvg是强类型为SVGSVGElement。



Answer 4:

const canvas =  document.getElementById('stage') as HTMLCanvasElement;


Answer 5:

而其他的答案推动型的断言(这是它们是什么-打字稿没有类型转换 ,实际上改变的类型;它们仅仅是抑制类型检查错误的方式),在理智的诚实方式来处理你的问题是听错误消息。

在你的情况下,有3件事情可能出错:

  • document.getElementById("mycanvas")可能返回null ,因为没有该ID的节点被找到(它可能已被重命名,不注射到文档的是,有人可能试图在环境中运行的功能,无需访问DOM)
  • document.getElementById("mycanvas")可能会返回一个DOM元素的引用,但这DOM元素不是HTMLCanvasElement
  • document.getElementById("mycanvas")没有返回一个有效的HTMLElement ,这的确是一个HTMLCanvasElement ,但CanvasRenderingContext2D不受浏览器的支持。

相反,(自己的情况下像一个无用的错误消息,并且可能发现告诉编译器闭嘴Cannot read property 'getContext' of null抛出),我建议采取控制您的应用程序边界。

确保元素包含HTMLCanvasElement

const getCanvasElementById = (id: string): HTMLCanvasElement => {
    const canvas = document.getElementById(id);

    if (!(canvas instanceof HTMLCanvasElement)) {
        throw new Error(`The element of id "${id}" is not a HTMLCanvasElement. Make sure a <canvas id="${id}""> element is present in the document.`);
    }

    return canvas;
}

确保渲染上下文浏览器支持

const getCanvasRenderingContext2D = (canvas: HTMLCanvasElement): CanvasRenderingContext2D => {
    const context = canvas.getContext('2d');

    if (context === null) {
        throw new Error('This browser does not support 2-dimensional canvas rendering contexts.');
    }

    return context;
}

用法:

const ctx: CanvasRenderingContext2D = getCanvasRenderingContext2D(getCanvasElementById('mycanvas'))

ctx.fillStyle = "#00FF00";
ctx.fillRect(0, 0, 100, 100);

见打字稿游乐场 。



文章来源: TypeScript: problems with type system