Programing

TypeScript : 유형 시스템 문제

lottogame 2020. 9. 20. 10:30
반응형

TypeScript : 유형 시스템 문제


VisualStudio 2012에서 typescript를 테스트하고 있으며 유형 시스템에 문제가 있습니다. 내 HTML 사이트에는 ID가 "mycanvas"인 캔버스 태그가 있습니다. 이 캔버스에 직사각형을 그리려고합니다. 다음은 코드입니다.

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가 내 캔버스 요소에 확실히 존재합니다. 하지만이 문제는 해결하기 쉬울 것이라고 생각했습니다. 캔버스에 대한 유형 설명을 추가했습니다.

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는 실제로 동적 호출을 지원하지 않으며 내 문제는 typecast로 해결할 수 있습니다. 내 질문은 기본적 으로이 TypeScript 의 복제본입니다 .HTMLElement 캐스팅


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 에서 다양한 유형을 볼 수 있습니다 .


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

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 캔버스 태그가 명시 적으로 표시되는 "상수 오버로드"섹션을 참조하십시오.


나는 같은 문제가 있었지만 HTMLCanvasElement 대신 SVGSVGElement를 사용했습니다. 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로 강력하게 입력됩니다.


다른 답변은 유형 어설 션을 장려하지만 (그게 바로 TypeScript에는 유형 을 실제로 변경하는 유형 캐스트 가 없습니다 . 유형 검사 오류를 억제하는 방법 일뿐입니다) 문제에 접근하는 지적으로 정직한 방법은 오류 메시지.

귀하의 경우 잘못 될 수있는 세 가지가 있습니다.

  • document.getElementById("mycanvas") might return null, because no node of that id is found (it might have been renamed, not injected to the document yet, someone might have tried running your function in an environment without access to DOM)
  • document.getElementById("mycanvas") might return a reference to a DOM element, but this DOM element is not a HTMLCanvasElement
  • document.getElementById("mycanvas") did return a valid HTMLElement, it is indeed an HTMLCanvasElement, but the CanvasRenderingContext2D is not supported by the browser.

Instead of telling the compiler to shut up (and possibly finding yourself in a situation where a useless error message like Cannot read property 'getContext' of null is thrown), I recommend taking control over your application boundaries.

Make sure the element contains a 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;
}

Make sure the rendering context is supported by the browser

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

Usage:

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

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

See TypeScript Playground.

참고URL : https://stackoverflow.com/questions/13669404/typescript-problems-with-type-system

반응형