typescript2.0 - Skillnader mellan gränssnitt i Typescript?
Jag har ett par gränssnitt:
interface ISubstitution {
id: number;
name: string;
date: string;
subject: number;
new: string;
group: number;
form: boolean;
}
interface ISubstitutionHot {
new: string;
group: number;
form: boolean;
}
Motsvarande är ett objekt av gränssnittstyp:
public a: any;
a = <ISubstitution> {
id: 1,
name:"O",
date: "2018-01-1",
subject: "M",
new: "A",
group: 1,
form: true
}
Observera att ISubstitutionHot utökar ISubstitution.
Så, sammanfattningsvis har jag fyllt objekt a.
Hur man tar skillnaden mellan objekt/gränssnitt som:
let c = <a>ISubstitution / <b>ISubstitutionHot;
För att bara hämta fält från objektet a som finns i gränssnittet ISubstitutionHot? Det borde returnera mig:
c = {
new: "A",
group: 1,
form: true
}
Är det möjligt i TypeScript?
Svar #1
Typer och gränssnitt i TypeScript existerar endast vid kompilerings-/design-tid, och tas bort när koden kompileras till JavaScript. Det betyder att det enda sättet att få något att hända vid körning är om du placerar den information du behöver i ett värde och inte bara i en typ. Här är ett sätt att gå vidare:
Först, definiera hotKeys, en array av strängarna "new", "group" och "form". Funktionen keyArray() är bara en hjälpfunktion som tillåter TypeScript att härleda de literala typerna istället för bara string[]:
const keyArray = <K extends string>(...keys: K[]) => keys;
const hotKeys = keyArray('new', 'group', 'form');
type HotKeys = typeof hotKeys[number];
Om du inspekterar det, är hotKeys av typen ('new' | 'group' | 'form')[], och därför är HotKeys 'new' | 'group' | 'form'.
Nu kommer vi att definiera pick()-funktionen, som tar ett objekt och en array av nycklar från det objektet och returnerar ett annat objekt med endast de egenskaper som motsvarar de nycklarna. Så här:
function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
const ret = {} as Pick<T, K>; // empty to start
keys.forEach(k => ret[k] = obj[k]); // copy some properties
return ret;
}
Detta är en generisk funktion som använder den inbyggda Pick-mappade typen.
Om du vill kan du antingen definiera ISubstitutionHot som ett gränssnitt på det sätt du har gjort, eller så kan du definiera det i termer av ISubstitution och HotKeys så här:
type ISubstitutionHot = Pick<ISubstitution, HotKeys>;
// { new: string; group: number; form: boolean; }
Slutligen, låt oss skriva funktionen som konverterar en ISubstitution till en ISubtitutionHot:
function iSubstitutionHot(iSub: ISubstitution): ISubstitutionHot {
return pick(iSub, hotKeys);
}
Det faktum att ovanstående funktion typkontrolleras utan fel är en indikation på att vi är på rätt spår.
Okej, låt oss prova det:
const a: ISubstitution = {
id: 1,
name: "O",
date: "2018-01-1",
subject: 1, // "M" <-- number!
new: "A",
group: 1,
form: true
}
let c = iSubstitutionHot(a);
console.log(c); // { new: "A", group: 1, form: true }
Det fungerar! Du kan se koden i aktion här. Hoppas det hjälper. Lycka till.
