Description
TS heavily relies on type assertion in DOM programming. In my experiences, type assertion is a major factor of produtivity-reduction in font-end TS. There is another user expressed similar concern (#3263).
So I try to eliminate most type assertions in DOM programming by adding a UniveralElement
interface to lib.d.ts
, see my fork of lib.es6.d.ts
.
In my fork, querySelector()
, getElementById()
, getElementsByClassName()
, children
, firstElementChild
etc. return UniversalElement
or a list of UniversalElement
, which inherits all known sub interfaces of Element
; UIEvent::target
is typed as UniversalUIEventTarget
, which extends UniversalElement
, Document
, and Window
. So in most case so you don't have to cast the result before use anymore. Additionally you don't loose the power of type check and autocompletion.
A snapshot of autocompletion using my prototype:
And some sample codes:
/// <reference path="lib.es6.d.ts" />
var ue = document.querySelector('#foo'); // UniversalElement
// from Element
var cls: string = ue.className;
// from HTMLElement
ue.blur();
// from HTMLMediaElement
ue.play();
// from HTMLInputElement
var files = document.querySelectorAll('input[type=file]')[0].files;
var fname = files[0].name;
// from HTMLImageElement
var nh = document.body.children[0].naturalHeight;
var svg = document.getElementsByClassName("bar")[0];
// from SVGElement
var vp = svg.viewportElement;
// from SVGLineElement
svg.x1.baseVal.newValueSpecifiedUnits(1, SVGLength.SVG_LENGTHTYPE_PX);
// type of href from HTMLAnchorElement becomes "any" because of type confliction
// with SVGElements
var href = document.querySelector('a').href;
// UIEvent::target is UniversalUIEventTarget, which extends UniversalElement,
// Document, and Window
document.addEventListener('mousemove', ev => {
var targ = ev.target;
if (targ.classList.contains('movable')) {
targ.style.left = ev.pageX + 'px';
targ.style.right = ev.pageX + 'px';
}
});