Hur lägger man till en egenskap till ett befintligt objekt för att uppfylla ett gränssnitt i TypeScript?


Här är vad jag skulle vilja göra i korthet:

interface A {
     prop1: string;
}

interface B extends A {
    prop2: string;
}

someImportantFunction(x: A): B {
    var ret: B = x.prop2 = someCalculation(); //Error, but if possible x would now satisfy B

    return ret;
}

Den engelska versionen av min fråga är: hur kan jag lägga till nya egenskaper till ett befintligt objekt i TypeScript, med målet att uppfylla en mer härledd gränssnittsdefinition? Kanske är detta inte möjligt, eller så missar jag någon uppenbar metod.

UPPDATERING: Antag också att listan över egenskaper på gränssnitt A är lång, så rutinmässig tilldelning genom att mappa egenskaper är arbetsam och inte ren.

Jag ser också att något liknande detta skulle fungera, men det verkar vara ett hack:

someImportantFunction(x: A): B {
    var ret: B = <B>x;
    ret.prop2 = someCalculation();

    return ret;
}

Tack, Mathias

Svar #1

Med intersektionstyper (TS 1.6+) kan du få mer typkontroll:

// your typical mixin function, like lodash extend or jQuery.extend
// you can use one of those instead of this quick and dirty implementation,
// the main reason for having this function is its type signature
function extend<T1, T2>(source: T1, addition: T2): T1 & T2 {
  let result = <T1 & T2>source;
  for(let key of Object.keys(addition)) {
    result[key] = addition[key];
  }
  return result;
}

interface A {
  prop1: string;
}

interface B extends A {
  prop2: string;
}

function someImportantFunction(x: A): B {
  return extend(x, {
    prop2: someCalculation()
  });
}

På så sätt kan kompilatorn avgöra vilka egenskaper av typen B som saknas i typen A och säkerställa att ditt extend-anrop tillhandahåller dem.

Svar #2

Använd Object.assign:

interface A { prop1: string; }
interface B extends A { prop2: string; }

someImportantFunction(x: A): B {
    var ret: B = Object.assign(x, { prop2 : someCalculation()});

    return ret;
}

Typerna kommer fram eftersom typningsfilen definierar returvärdena som en intersections typ (&):

assign<T, U>(target: T, source: U): T & U;

Relaterade artiklar