Typescript: The return value of function type is not checked when function may return any

Created on 26 Nov 2020  路  2Comments  路  Source: microsoft/TypeScript

TypeScript Version: 4.2.0-dev.20201124

Search Terms:

function, type check, any

Code

const f1: () => number = () => {
  if (window) {
    return {} as any;
  }
  return "a"; // Pass
};

// Expected behavior
const f2: () => number = () => {
  return "a"; // Error: Type '() => string' is not assignable to type '() => number'
};

// Expected behavior
function f3(): number {
  if (window) {
    return {} as any;
  }
  return "a"; // Error: Type 'string' is not assignable to type 'number'.
};

Expected behavior:

f1 causes an error because it returns a string.

Actual behavior:

f1 does not cause an error.

Playground Link:

https://www.typescriptlang.org/play?ts=4.2.0-dev.20201124#code/MYewdgzgLgBAZgRgFwwBQEoYF4B8MwCuAtgEYCmATtmprjAN4BQMMAlnGgO6tgAmInTExYsKZKAQpgGAXxgBDCArABPANzMYMzWIlSYAInkG1MAPRmYABUURGMjYwswAogA8ADmWBQyvGOQAFvIAbqwgFIygkLBwAEwoGNh4hKSU1El0wjC6ktJGJuaWLhQUESgAKipeMADkmXjQFDwA5rVsSmAgsLasLWDyJAA2ZDBQIGPVo-W0KcTkFLX2js7uXj5+AWTBYRGMcARgPuHScADMGCipCwya7Fw8-IK3IjniebIKSvKqGizaone+gKplWpXKMCqNVqTVa7VYnW6XwgfQGw1G40m0OulFqADplowgA

Experimentation Needed

Most helpful comment

TypeScript does not infer types from the variable that a value is assigned to.

In third example, the function is annotated to return number, thus returning a string is an error.

In your second example, the function is inferred to be of the type () => string, and like the error says, this type is not assignable to the type of the variable which is () => number.

In your first example, however, the function is inferred to return the type any | string, which is the same as any, and thus the whole function is of type () => any. This type _is_ assignable to () => number, as any is assignable to number.

The solution is to attach type annotations directly to the function:

const f1 = (): number => {
  if (window) {
    return {} as any;
  }
  return "a"; // Error: Type 'string' is not assignable to type 'number'.
};

All 2 comments

TypeScript does not infer types from the variable that a value is assigned to.

In third example, the function is annotated to return number, thus returning a string is an error.

In your second example, the function is inferred to be of the type () => string, and like the error says, this type is not assignable to the type of the variable which is () => number.

In your first example, however, the function is inferred to return the type any | string, which is the same as any, and thus the whole function is of type () => any. This type _is_ assignable to () => number, as any is assignable to number.

The solution is to attach type annotations directly to the function:

const f1 = (): number => {
  if (window) {
    return {} as any;
  }
  return "a"; // Error: Type 'string' is not assignable to type 'number'.
};

@ChayimFriedman2 is correct, but I think it would be a palatable breaking change to check assignability of return expressions to the contextual type's return type when one is present. The real problem might be introducing some new circularities, but issuing an error on f1 is entirely justifiable IMO. Someone can give it a try if they want.

Was this page helpful?
0 / 5 - 0 ratings