Reputation: 1283
I am trying to define a function type with a return type (Object) to enforce functions implementing it to return the exact object properties defined in the return type.
However the compiler is not being strict about the returned object and allows extra properties that are not defined in the returned object type.
interface Obj {
foo: string;
}
type Func = () => Obj;
const fn: Func = () => {
return {
foo: 'bar',
blah: '', // compiler does not show an error
};
};
In contrast, if the return type Obj
is specified in the fn
function, the compiler shows an error.
interface Obj {
foo: string;
}
const fn = (): Obj => {
return {
foo: 'bar',
blah: '', // compiler shows an error
};
};
Can somebody explain why TS handles these cases differently? Is there a way to have the return type strictness while using a function type?
Upvotes: 7
Views: 876
Reputation: 469
In the first example, the return type of the anonymous function is defined dynamically as follow: { foo: string; blah: string; }
. This type is compatible with the type Obj
as it has all the required properties of Obj
(and more, but that's enough to be considered compatible, as "structural typing is a way of relating types based solely on their members", from https://www.typescriptlang.org/docs/handbook/type-compatibility.html).
In the end, the Func
type is compatible with the silently defined type of the anonymous function () => { foo: string; blah: string; }
, so an "implicit conversion" takes place and it compiles.
In the second example, the signature enforces the return type of the anonymous function itself, so the returned object is a literal that's supposed to be exactly of type Obj
. Thus, for the same reason you can't do: let obj: Obj = { foo:'bar', blah:'' }
, this code can't compile because there's no compatibility check in this case, as its type is explicitly defined.
Upvotes: 5