I've created this example in the TypeScript playground:
interface Test{
a: string
b: string
}
const object: Test = {
a: 'b',
b: 'c',
}
function testIt(): Test[] {
const data = [{b: '2', c: '3'}]
const prices: Test[] = data.length ? data.map((item) => {
return {
a: item.b,
b: item.c,
c: '2',
d: '3'
}
}) : [];
return prices;
}
Removing either a or b property from the object return statement in the array map method results in a TypeScript error (as expected).
Adding c or d or any other random unknown property does not trigger a TypeScript error. I would suspect that this is only possible if the interface contains [x: string]: any.
So why does Array.map do type checking on missing properties on an interface but not on additional / unknown properties?
The syntax for the map() method is as follows: arr. map(function(element, index, array){ }, this); The callback function() is called on each array element, and the map() method always passes the current element , the index of the current element, and the whole array object to it.
Return Value: This method returns the created array. Below examples illustrate the Array map() method in TypeScript.
To convert an array of objects to a Map :Use the Map() constructor to create a new Map . Call the forEach() method on the array. On each iteration, add the key-value pair to the new Map .
Use Map type and new keyword to create a map in TypeScript. let myMap = new Map<string, number>(); To create a Map with initial key-value pairs, pass the key-value pairs as an array to the Map constructor.
The problem is that according to basic OOP rules, a derived type (ie one with more properties) should be compatible with the base type (ie. the type with just a
and b
).
This being said, typescript does warn us when assigning object literals with more properties where a type with fewer properties is expected. This is called excess property checking. This feature only kicks in on DIRECT assignment to something that is o a given type.
The reason this excess property check does not apply in your case is the way type checking is done for map
. First the callback return type is inferred based on the object literal, so it is inferred as { a: string, b: string, c: string, d: string }
. Then this type is used as the return type for map
, so map
will return an Array<{ a: string, b: string, c: string, d: string }>
. This is then assigned to Test[]
which under the first rule is allowed. Nowhere did we assign an object literal to a place where Test
was expected.
One way to get an error is to not let typescript infer the result of callback passed to map
. We can do this by adding the annotation to the callback. Then we are directly assigning an object literal to a location that expects Test
:
const prices = data.length ? data.map((item) : Test => {
return {
a: item.b,
b: item.c,
c: '2', // error
d: '3'
}
}) : [];
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