yazfield
yazfield

Reputation: 1283

Function type not enforcing the same strictness as return type

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

Example in TS playground

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

Example in TS playground

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

Answers (1)

tooomg
tooomg

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

Related Questions