Hvilket TypeScript-mønster kan jeg bruke for å sikre at en funksjon får en egenskap?
I JavaScript kan jeg gjøre dette:
function f() {}
f.prop = "property";
Jeg vil ha dette i TypeScript, men med typetesting.
Utover klasser, hvilken TypeScript-mønster kan jeg bruke for å sørge for at en funksjon får en egenskap?
Kan jeg bruke et grensesnitt?
interface functionWithProperty {
(): any;
prop: string;
}
Dette ser ut til å være et gyldig grensesnitt i TypeScript, men hvordan implementerer jeg dette grensesnittet slik at TypeScript-kompilatoren sjekker at prop er satt?
Jeg så dette eksemplet:
var f : functionWithProperty = (() => {
var _f : any = function () { };
_f.prop = "blah";
return _f;
}());
Men dette fungerer ikke fordi jeg kan fjerne _f.prop="blah"; og alt vil fortsatt kompilere. Jeg trenger å sørge for at prop blir satt.
Svar #1
Jeg tror du trenger å omfavne objektorienteringen i TypeScript og lage en klasse med egenskaper og funksjoner.
Å kombinere funksjoner og egenskaper slik du har i eksemplet ditt er gyldig JavaScript, men hvis du tar steget over til TypeScript, kan du like gjerne bli helt oppslukt i det.
class MyClass {
constructor(public myProp: string) {
}
myFunc(): string{
return this.myProp;
}
}
Oppdatering
Ansvarsfraskrivelse: Jeg anbefaler ikke å gjøre ting på denne måten - som jeg har sagt, anbefaler jeg å bruke de strukturelle funksjonene i TypeScript for å organisere koden din på den mest lesbare måten du kan.
Du kan imidlertid definere typen på funksjonen din hvis du ønsker det ved å bruke en typedeklarasjon:
var f: { (): void; prop: string; } = (() => {
var _f : any = function () {
alert(_f.prop);
};
_f.prop = "blah";
return _f;
}());
f();
Dette lar de som kaller f få autofullføring og typkontroll, men vil ikke føre til at innholdet i f blir sjekket for å sikre at det overholder kravene - fordi du er «under panseret» på dette stadiet - så du kunne skrive dette...
var f: { (): void; prop: string; } = (() => {
var _f : any = undefined;
return _f;
}());
f();
Hvis du vil få typekontroll på definisjonen av f i tillegg til å få sjekket kall til f, må du se på klasser.
Svar #2
Du kan håndtere dette ryddig og med full typeinformasjon ved å utnytte deklarasjonssammenslåing og strukturell typening!
interface functionWithProperty {
(): any;
prop: string;
}
function MyCoolFunc() {
return "yay";
}
module MyCoolFunc {
export var prop: string = "wow";
}
// this will compile without errors, MyCoolFunc implements the
// functionWithProperty interface (structurally)
let x: functionWithProperty = MyCoolFunc;
console.log(x.prop, x());
console.log(MyCoolFunc.prop, MyCoolFunc());
// this would result in a compiler error
// let y: functionWithProperty = console.log;
Den kompilert JavaScript vil se mye ut som eksemplet du ga i spørsmålet, men TypeScript-kompilatoren vil vite nøyaktig hva som foregår! I utgangspunktet blir moduldeklarasjonen av MyCoolFunc lagt til i funksjonsdeklarasjonen, noe som resulterer i en funksjon med en egenskap.
Hvis du vil fastslå ved kompileringstid at MyCoolFunc implementerer functionWithProperty riktig, kan du ha en ikke-eksportert variabeldeklarasjon i modulen din som den i eksemplet ovenfor.
