mathias999us
mathias999us

Reputation: 357

How to add a property to an existing object to satisfy an interface in typescript?

Here's what I would like to do in a nutshell:

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;
}

The english version of my question is: how can I add new properties to an existing object in typescript, with the goal of satisfying a more-derived interface definition? Perhaps this is not possible, or I am missing some obvious approach.

UPDATE: Also, suppose the list of properties on interface A is long, so boilerplate assignment by mapping properties is laborious and not clean.

I also see something like this would work, but it seems like a hack:

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

    return ret;
}

Thanks, Mathias

Upvotes: 11

Views: 11696

Answers (3)

Fowl
Fowl

Reputation: 5128

Use 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;
}

The types come out because of the typing file defines the return values as an intersection type (&):

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

Upvotes: 6

user1233508
user1233508

Reputation:

With intersection types (TS 1.6+), you can have more type safety:

// 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()
  });
}

This way the compiler can determine what properties of type B are missing from type A and ensure your extend call provides them.

Upvotes: 6

CoderPi
CoderPi

Reputation: 13211

It's more a JavaScript-Problem:

function someImportantFunction(x: A): B {
    var ret: B = {
        prop1: x.prop1,
        prop2: someCalculation()
    }

    return ret;
}

but you could also do:

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

    return ret;
}

Upvotes: 0

Related Questions