Interface is allowing extra property when it is used as return type of a function

An inteface seems to accept extra property(ies) when it is assigned as a return of a function via a type.

In general, TypeScript uses structural typing, so it is perfectly fine to assign an object with additional properties to a Human interface.

const lui = {
  name: "Lui",
  age: 40
}

const human: Human = lui // works, 

You can assign lui to variable human with type Human, because typeof lui is a sub-type and therefore has the same/compatible property members.

An exception to this rule are excess property checks for “freshly created object literals”, that are intended as developer aid and prohibit extra properties to be added. The general thought here is, that you exactly know what properties you want, when you define a direct object literal with no other indirection (access of variables etc. to get that object value).

Excess property checks require an immediately following explicit type annotation at the variable, property or function dealing with the fresh object literal in order to work. Otherwise the object literal type doesn’t count as “fresh” anymore (its type is widened). Let’s check your examples to illustrate the concept.

const humanCreator: HumanCreator = (name, age) => ({
  name,
  age // No error. Why?
});

You can see this as an assignment of a type compatible function to the variable with type HumanCreator. The compiler looks at the function expression (name, age) => ({ name, age }), infers parameter types and makes sure that its return type is compatible to the variable type. And indeed – {name: string; age:number} return type is assignable to Human (structural typing).

const humanCreatorr: HumanCreator = (name, age): Human => ({
  name,
  age // Error
});

const humanCreatorrr = (): Human => ({
  name: '',
  age: 0 // Error
});

These cases are different, as you immediately annotate the functions with Human return type. There is no type inference for the return type necessary for the compiler. tl;dr To enable excess property checks, annotate an explicit type for your object literal as close as possible.

Further links

Leave a Comment