typescript - Utvide typedefinisjon i variabel definert i lib.d.ts
Jeg har eldre kode som må transformeres som bruker mootools. Mootools introduserer en ny konstruktørfunksjon av 'Element' med to parametere. Jeg fant ingen type-definisjonsfil for mootools, så jeg må skrive min egen.
Typescript-standardbiblioteket (lib.d.ts) definerer Element som følger:
var Element: { prototype: Element; new(): Element; };
som gjør det umulig å utvide et eksisterende grensesnitt.
Det jeg åpenbart prøvde er
interface Element {
new(s: string, s2: any): Element;
}
Men likevel klager kompilatoren over
var c = new Element('p',{});
siden konstruktøren forventet 0 argumenter, men fikk 2. Hva er den foretrukne løsningen her?
Mootools-konstruktørfunksjonen
var Element = this.Element = function(tag, props){
var konstructor = Element.Constructors[tag];
if (konstructor) return konstructor(props);
if (typeof tag != 'string') return document.id(tag).set(props);
if (!props) props = {};
if (!(/^[\w-]+$/).test(tag)){
var parsed = Slick.parse(tag).expressions[0][0];
tag = (parsed.tag == '*') ? 'div' : parsed.tag;
if (parsed.id && props.id == null) props.id = parsed.id;
var attributes = parsed.attributes;
if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){
attr = attributes[i];
if (props[attr.key] != null) continue;
if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value;
else if (!attr.value && !attr.operator) props[attr.key] = true;
}
if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ');
}
return document.newElement(tag, props);
};
// Browser
var Browser = this.Browser = parse(navigator.userAgent, navigator.platform);
if (Browser.Element){
Element.prototype = Browser.Element.prototype;
// IE8 and IE9 require the wrapping.
Element.prototype._fireEvent = (function(fireEvent){
return function(type, event){
return fireEvent.call(this, type, event);
};
})(Element.prototype.fireEvent);
}
Svar #1
Du trenger ikke å utvide Element-grensesnittet, det du trenger er å utvide typen til Element-variabelen. Det er litt forvirrende, det er to separate enheter fra TS sitt ståsted. Slik kan du gjøre det:
declare const Element: { // If you do that in a .d.ts file, you don't need declare.
prototype: Element; // Element here is interface, we leave it unchanged.
new(): Element; // Standard constructor.
new(s: string, n: number): Element; // Your custom constructor.
};
const e = new Element('1', 2);
e.nodeName; // => string, i.e. result object implements Element interface.
