0

I am trying to type a function in TypeScript:

Here everything is OK

const myFunction_1 = (param1: number, param2: number): number => {
    return param1 + param2;
};

const result_1 = myFunction_1(1, 2);
console.log(result_1);

Here an error shown, as nothing is returned: A function whose declared type is neither 'void' nor 'any' must return a value.

const myFunction_2 = (param1: number, param2: number): number => {};

const result_2 = myFunction_2(1, 2);
console.log(result_2);

Here everything is ok

type myFunction_3Type = (param1: number, param2: number) => number;

const myFunction_3: myFunction_3Type = (param1: number, param2: number) => {
    return param1 + param2;
};

const result_3 = myFunction_3(1, 2);

And here is the interesting part. I declare two interfaces: one for the input of the function and another for the output. I use them in the type myFunction_4Type; Then I use this type in the function, and I force the function to return an object that doesn't match the output interface; but it doesn't display an error!

interface IMyFunctionInput {
    a: number;
    b: number;
}

interface IMyFunctionOutput {
    a: number;
    b: number;
}

type myFunction_4Type = (payload: IMyFunctionInput) => IMyFunctionOutput;

const myFunction_4: myFunction_4Type = payload => {
    return {
        a: 1,
        b: 2,
        c: 3 // This key and prop should cause an error, as it doesn't match the interface IMyFunctionOutput
    };
};

const payload = {
    a: 1,
    b: 2
};

const result_4 = myFunction_4(payload);

Any help will be welcome : )

1 Answers1

2

It looks like you have two distinct problems. The first is A function whose declared type is neither 'void' nor 'any' must return a value. Your function myFunction_2 has a declared return type of number but the function body is { } which returns nothing.

You have two options, either define the return type as void:

const myFunction_2 = (param1: number, param2: number): void => {};

Or return a number:

const myFunction_2 = (param1: number, param2: number): number => { return 1 };

The second problem is a feature of TypeScript: https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks

One option is to first assign it to a variable to take advantage of the excess property checking as stated in the documentation:

Object literals get special treatment and undergo excess property checking when assigning them to other variables, or passing them as arguments. If an object literal has any properties that the “target type” doesn’t have, you’ll get an error:

const myFunction_4: myFunction_4Type = payload => {
    const value: IMyFunctionOutput = {
        a: 1,
        b: 2,
        c: 3 // Object literal may only specify known properties, and 'c' does not exist in type 'IMyFunctionOutput'.
    };

    return value;
};

Another option pointed out by jcalz:

const myFunction_4 = (payload: IMyFunctionInput): IMyFunctionOutput => {
    return {
        a: 1,
        b: 2,
        c: 3 // Object literal may only specify known properties, and 'c' does not exist in type 'IMyFunctionOutput'.
    };
};

Also, see this overview for more details: https://basarat.gitbooks.io/typescript/docs/types/freshness.html

Another possible solution is shared here: https://stackoverflow.com/a/54775885/2690790

skovy
  • 5,430
  • 2
  • 20
  • 34
  • 2
    FYI It's considered a language design limitation that [excess property checking does not happen for return types of function-typed values](https://github.com/microsoft/TypeScript/issues/7547). Your answer is a reasonable workaround. Another is to change `payload =>` to `(payload): IMyFunctionOutput =>`. – jcalz Aug 27 '19 at 18:10
  • Thanks! I am aware of the error `A function whose declared type is neither 'void' nor 'any' must return a value.`, nothing to comment there :) –  Aug 27 '19 at 18:19
  • About the issue with `myFunction_4`, I'm just reading about excess property checks. It is interesting, I'm trying to understand why is this useful… –  Aug 27 '19 at 18:20