Home > OS >  TypeScript: Arrow function parameter causes Property is missing in type '{}' but required
TypeScript: Arrow function parameter causes Property is missing in type '{}' but required

Time:12-27

According to TypeScript's documentation on interfaces,

An interface declaration is another way to name an object type.

If that's the case, why do I get an error in the code below? I'm trying to "narrow" down the object type in the arrow function parameter with an interface.

(TypeScript Playground Link)

interface Person {
  name: string;
}

type ObjToString = (obj: object) => string;

const personToString: ObjToString = (obj: Person) => obj.name;
// This causes the error                  ^^^^^^

Error message:

Type '(obj: Person) => string' is not assignable to type 'ObjToString'.
  Types of parameters 'obj' and 'obj' are incompatible.
    Property 'name' is missing in type '{}' but required in type 'Person'.

However, I can assign a variable of type Person to a variable of type object:

let obj: object;
const person: Person = { name: "Tom" };
obj = person;  // OK

Is there any reason why the error occurs at the arrow function parameter only? How can I fix this problem?

CodePudding user response:

You are trying to assign a function that requires a Person object to a function that is typed to accept any object. IOW, you could then call personToString as follows:

personToString({ whatever: "hello" });

Obviously this cannot work, which is why the compiler complains.

CodePudding user response:

object type itself does not have any properties. And that is the issue you are getting. object is a very restrictive type.

If you want to use any type of object, just use any.

type ObjToString = (obj: any) => string;

interface Person {
  name: string;
}

const personToString: ObjToString = (obj: Person) => obj.name;

Link

Also, Typescript's behaviour is such that does not complain when you pass extra properties to a type which was expecting lesser properties. But it would definitely complain is the minimum required properties are not present.

Look at this example :

interface Student {
  school : string;
  name : string;
}

interface Human {
name : string;
}

let x : Student = {
  name: 'Test',
  school: 'Test'
};

let y : Human = {
  name : 'test'
};

// x = y;
y = x;

The statement x=y will give an error but y=x will not do it. You can assign Student to Human, but not Human to Student.

Link

That is what is happening in your code, TS is complaining because Person requires name and it is missing in object ({}). object requires nothing and name is just an extra property being passed to the variable obj.

Related

CodePudding user response:

The TypeScript object type represents all values that are not in primitive types.

The main issue here is trying to access a property called 'name' from an 'object' which is translated to {} and does not have 'name' property.

you could help Typescript understand what you are trying to do by using generics:

    interface Person {
      name: string;
    }
    type ObjToString<T> = (obj: T) => string;
    const personToString: ObjToString<Person> = (obj: Person) => obj.name;

    const aPerson: Person = {name: 'test_name'};
    const aPersonName = personToString(aPerson);
    console.log(aPersonName)
  • Related