TypeScript: tür sistemiyle ilgili sorunlar


102

VisualStudio 2012'de typcript'i test ediyorum ve tip sistemiyle ilgili bir problemim var. HTML sitemde "mycanvas" kimliğine sahip bir canvas etiketi var. Bu tuvale bir dikdörtgen çizmeye çalışıyorum. İşte kod

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

Maalesef VisualStudio bundan şikayet ediyor

'getContext' özelliği 'HTMLElement' türünün değerinde mevcut değil

İkinci satırı bir hata olarak işaretler. Bunun sadece bir uyarı olacağını düşündüm ama kod derlenmiyor. VisualStudio diyor ki

yapı hataları vardı. Son başarılı derlemeye devam etmek ve çalıştırmak ister misiniz?

Bu hatayı hiç beğenmedim. Neden dinamik yöntem çağrısı yok? Sonuçta getContext yöntemi kesinlikle tuval öğemde var. Ancak bu sorunun çözülmesinin kolay olacağını düşündüm. Tuval için bir tür ek açıklaması ekledim:

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

Ancak tip sistemi hala tatmin olmadı. İşte yeni hata mesajı, bu sefer ilk satırda:

'HTMLElement', 'HTMLCanvasElement'e dönüştürülemiyor:' HTMLElement 'türünde' HTMLCanvasElement 'türünden' toDataURL 'özelliği eksik

Tamamen statik yazmayı seviyorum ama bu, dili kullanılamaz hale getiriyor. Yazı sistemi ne yapmamı istiyor?

GÜNCELLEME:

Typescript gerçekten dinamik çağrı için destek sağlamıyor ve benim sorunum tipcast ile çözülebilir. Sorum temelde bu TypeScript'in bir kopyası: HTMLElement yayınlama

Yanıtlar:


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

veya anytürle dinamik arama kullanma (yazım denetimi yok):

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

Lib.d.ts'deki farklı türlere bakabilirsiniz .


9
Tuval bağlamı için yazı yazmak CanvasRenderingContext2Dyerine kullanmanın daha iyi olduğunu belirtmekte fayda var any.
Ivan Kochurkin

3
Typescript 1.8 yana, sabit dize argümanı tanıyacak "2d"ve .getContext("2d")tipiyle dönecektir CanvasRenderingContext2D. Açıkça yayınlamanıza gerek yok.
Markus Jarderot

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

7
Lütfen bu kodun neden sadece bir kod cevabı değil de OP'nin problemini çözmeye yardımcı olduğunu açıklayın. Kodunuz neyi farklı yapıyor, nasıl yardımcı oluyor?

Kopyala / yapıştır ve işe yarıyor. Burada ne açıklanmalı? Sizin için işe yaramazsa, o zaman size sorununuzu anlatmalı ve daha spesifik olarak sormak.
lenooh

7

Diğer yanıtlar tür iddialarını teşvik ederken (işte bunlar - TypeScript, türü gerçekten değiştiren tür dökümlerine sahip değildir ; bunlar yalnızca tür kontrol hatalarını bastırmanın bir yoludur), sorununuza yaklaşmanın entelektüel olarak dürüst yolu, hata mesajları.

Senin durumunda ters gidebilecek 3 şey var:

  • document.getElementById("mycanvas")dönebilir null, çünkü bu kimliğin hiçbir düğümü bulunamaz (yeniden adlandırılmış olabilir, henüz belgeye eklenmemiş olabilir, birisi DOM'a erişimi olmayan bir ortamda işlevinizi çalıştırmayı denemiş olabilir)
  • document.getElementById("mycanvas") bir DOM öğesine bir başvuru döndürebilir, ancak bu DOM öğesi bir HTMLCanvasElement
  • document.getElementById("mycanvas")geçerli bir döndürdü HTMLElement, bu gerçekten bir HTMLCanvasElement, ancak CanvasRenderingContext2Dtarayıcı tarafından desteklenmiyor.

Derleyiciye susmasını söylemek (ve muhtemelen kendini işe yaramaz bir hata mesajının Cannot read property 'getContext' of nullatıldığı bir durumda bulmak ) yerine, uygulama sınırlarınızı kontrol etmenizi öneririm.

Öğenin bir HTMLCanvasElement içerdiğinden emin olun

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;
}

Oluşturma bağlamının tarayıcı tarafından desteklendiğinden emin olun

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;
}

Kullanım:

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

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

TypeScript Playground konusuna bakın .



1

Aynı sorunu yaşadım, ancak HTMLCanvasElement yerine SVGSVGElement ile. SVGSVGElement'e çevrim yapmak derleme zamanı hatası verdi:

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

"HTMLElement", "SVGSVGElement" olarak dönüştürülemiyor: "HTMLElement" türünde, "SVGSVGElement
" türünden "genişlik" özelliği eksik.
"SVGSVGElement" türünde "HTMLElement" türündeki "onmouseleave" özelliği eksik.

İlk önce 'herhangi birine' atarak düzeltildiyse:

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

veya bu şekilde (aynı etkiye sahiptir)

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

Şimdi mySvg kesinlikle SVGSVGElement olarak yazılmıştır.


0

Bu eski bir konudur ... 2012'ye kadar ölü olabilir, ancak heyecan verici ve VS Code ve typcript için yeni.

Bunu VS Code'da aşağıdaki paket referanslarıyla çalıştırmak için aşağıdakileri yapmam gerekiyordu.

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

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

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

TypeScript Sürümü:

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

0

Sen eklemeniz gerekebilir DOMiçin compilerOptions.libGözlerinde farklı tsconfig.json.

// 'tsconfig.json'
 {
  "compilerOptions": {
    "target": "ES2017",
    "module": "commonjs",
    "lib": [
      "es5",
      "DOM",
      "esnext"
    ]
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.