Reputation: 4011
I would expect a type error in the following code, but for typescript is perfectly ok, can you tell me why?
export interface Structure {
aaa: string;
}
export function f1(): Structure[] { // OK for typescript, not for me
const result = [].map(certState => {
return {
aaa: 'aaa',
ADDITIONAL_FIELD: 'asdf'
}
});
return result;
}
export function f2(): Structure[] { // ERROR for typescript (and for me)
return [
{
aaa: 'sdf',
ADDITIONAL_FIELD: 'asdf'
}
]
}
Thanks!
Upvotes: 2
Views: 1164
Reputation: 4011
I just learn that Typescript has a concept of exact types only for object literals, so f1 is not using object literals, so additional properties cannot be add and it's valid for typescript. f2 uses object literals, so additional properties are not allowed. This scare me a lot, but that's how typescript works
Upvotes: 0
Reputation: 165
The error is due to the fact that in f2()
you are directly returning your result.
If you changed f2()
to be
export function f2(): Structure[] {
const returnVal = [
{
aaa: 'sdf',
ADDITIONAL_FIELD: 'asdf'
}
]
return returnVal;
}
then there would be no compiler error.
TypeScript uses structural typing to determine type compatibility, so in your code for f1()
, result
is of type
{
aaa: string,
ADDITIONAL_FIELD: string
}[]
which is compatible with Structure[]
(there is no danger in type narrowing).
I'm not 100% sure why directly returning doesn't work, but my assumption is that in f2()
you are telling the compiler that "this specific array is of type Structure[]
"
and it says no it's not. When you have an intermediate variable in f1()
you are saying "this function returns Structure[]
" and when you return the intermediate variable the compiler checks and says "okay result
matches Structure[]
" so this function is doing what it says.
I'd be curious to hear if others have a more rigorous explanation
Upvotes: 2