TypeScript:类型系统的问题

b1uwtaje  于 2022-11-26  发布在  TypeScript
关注(0)|答案(8)|浏览(163)

我正在测试VisualStudio 2012中的typescript,它的类型系统有问题。我的html站点有一个id为“mycanvas”的canvas标签。我试图在这个canvas上绘制一个矩形。代码如下

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

不幸的是VisualStudio抱怨说
型别'HTMLElement'的值上没有属性'getContext'
它将第二行标记为错误。我以为这只是一个警告,但代码没有编译。VisualStudio说
存在生成错误。是否继续并运行上次成功的生成?
我很不喜欢这个错误,为什么没有动态方法调用呢?毕竟getContext这个方法在我的canvas元素上是肯定存在的,不过我觉得这个问题很容易解决,我只是给canvas添加了一个类型注解:

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

但是类型系统仍然不满意,下面是新的错误消息,这次在第一行:
无法将“HTMLElement”转换为“HTMLCanvasElement”:类型'HTMLElement'遗漏类型'HTMLCanvasElement'的属性'toDataURL'
好吧,我完全支持静态类型,但是这使得语言无法使用。类型系统要我做什么呢?
最新消息:
Typescript确实不支持动态调用,我的问题可以通过类型转换来解决。

ktca8awb

ktca8awb1#

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中查看不同的类型。

rta7y2nd

rta7y2nd2#

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

icnyk63a3#

而其他的答案则提升了类型Assert(这就是它们的本质- TypeScript没有实际改变类型的 * 类型转换 *;它们仅仅是一种抑制类型检查错误的方法),那么解决问题的明智的诚实方法就是倾听错误消息。
在您的情况下,有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);

请参见TypeScriptPlayground。

dgsult0t

dgsult0t4#

这似乎在TypeScript的.9版本中得到了纠正:http://blogs.msdn.com/b/typescript/archive/2013/03/25/working-on-typescript-0-9-generics-overload-on-constants-and-compiler-performance.aspx请参阅“常量重载”一节,其中明确显示了画布标记。

t30tvxxf

t30tvxxf5#

我遇到了同样的问题,但是使用的是SVGSVGElement而不是HTMLCanvasElement。转换为SVGSVGElement会出现编译时错误:

var mySvg = <SVGSVGElement>document.getElementById('mySvg');
  • 无法将'HTMLElement'转换为'SVGSVGElement':

型别'HTMLElement'遗漏型别'SVGSVGElement'的属性'width'。
型别'SVGSVGElement'遗漏型别'HTMLElement'的属性'onmouseleave'。*
如果通过第一次强制转换为“any”来修复它:

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

或者这样(效果相同)

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

现在mySvg被强类型化为SVGSVGElement。

6rvt4ljy

6rvt4ljy6#

您可能需要将DOM添加到tsconfig.json中的compilerOptions.lib

// 'tsconfig.json'
 {
  "compilerOptions": {
    "target": "ES2017",
    "module": "commonjs",
    "lib": [
      "es5",
      "DOM",
      "esnext"
    ]
  }
}
kx7yvsdv

kx7yvsdv7#

这是一个老主题...也许死到2012年,但令人兴奋的和新的VS代码和 typescript 。
我必须执行以下操作才能在VS代码中使用以下包引用。

const demoCanvas: HTMLCanvasElement = document.getElementById('rfrnCanvas') as any;

        if(demoCanvas.getContext) {
            const context = demoCanvas.getContext('2d');

            if(context) {
                reactangle(context);
            }
        }

typescript 版本:

{
    "@typescript-eslint/eslint-plugin": "^2.29.0",
    "@typescript-eslint/parser": "^2.29.0",
    "typescript": "^3.7.5"
}
s71maibg

s71maibg8#

我建议

let canvas = document.getElementById('canvas') as
             HTMLCanvasElement;

相关问题