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
To add a property to an object in TypeScript, set the property as optional on the interface you assign to the object using a question mark. You can then add the property at a later point in time without getting a type error. Copied!
To use the Object. assign() method in TypeScript, pass a target object as the first parameter to the method and one or more source objects, e.g. const result = Object. assign({}, obj1, obj2) . The method will copy the properties from the source objects to the target object.
One way is to add a property using the dot notation: obj. foo = 1; We added the foo property to the obj object above with value 1.
To create an object based on an interface, declare the object's type to be the interface, e.g. const obj1: Employee = {} . The object has to conform to the property names and the type of the values in the interface, otherwise the type checker throws an error.
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;
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With