1

In the following code I defined the type of a function doSomething to be this type: (value: User) => User

Strangely when assigning a function with a wrong return type to doSomething then Typescript will not complain. Why is that?

interface User {
    userName: string;
}

const test: User = {
    userName: 'test',
    bla: '123' // OK:  TS complains
}

let doSomething: (value: User) => User;

doSomething = () => { // NOK: TS is not complaining about the missing parameter
  return {
    userName: 'test',
    bla: '123' // NOK: Why does TS not complain?
  }
};

Same thing happens when defining the type of a callback function and then pass a callback which returns a "wrong" value:

interface User {
    userName: string;
}

class Test {
    doSomething(callback: (value: User) => User): void {}
}

const test = new Test();

test.doSomething(() => { // NOK: TS is not complaining about the missing parameter
  return {
    userName: 'test',
    bla: '123' // NOK: Why does TS not complain?
  }
})

See example on stackblitz: https://stackblitz.com/edit/typescript-callback-2

3
  • Typescript doesn't do excess property checks on anything other than object literals, that's by design. Commented Mar 11, 2020 at 11:24
  • 1
    github.com/Microsoft/TypeScript/wiki/… Commented Mar 11, 2020 at 11:29
  • Nice JS forEach example: forEach(callback: (element?: T, index?: number, array?: T[])) which explains that skipping parameters is perfectly fine. Commented Mar 11, 2020 at 21:31

1 Answer 1

2

You can safely use a callback that has less parameters then the defined type, but not different or more:

test.doSomething(() => {...}                  // allowed
test.doSomething((user) => {...}              // allowed
test.doSomething((user1, user2) => {...}      // error
test.doSomething((username:string) => {...}   // error

This way you can provide a callback that probably doesn't need all values that it is called with.

Then you can safely add more properties to the returned object, but you can't skip mandatory ones or change their types:

return { userName: 'test', bla: '123'}   // ok, just an extra parameter
return { }                               // not ok, userName is required
return { userName: 42}                   // not ok, userName is required to be a string

It's ok because the receiver of the result can just ignore all extra properties, it causes no harm.

Sign up to request clarification or add additional context in comments.

1 Comment

I understand that skipping parameters is fine. As we never have to pass all parameters to e.g. `Array.forEach(callback: (element?: T, index?: number, array?: T[]))`` But the return Type of the callback which allows additional props feels a bit inconsistent when comparing to a standard class method: stackblitz.com/edit/typescript-callback-2-pwydkg

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.