1

In the example below, there are two places I can't wrap my head around, marked with (1) and (3)

Near (1), we're assigning a function which only knows how to handle string to a property which should know how to handle string | undefined. There's no TS error, and the succeeding call would result in a Runtime Error

Near (2), TS is able to correctly give an error, when arrow function is passed via reference, but near (3) when an arrow function is passed to be assigned to method which should handle string | undefined, everything is once again OK to Typescript (although it shouldn't)

I would really love to know why TS is behaving this way, since my example suggests that method and arrow function in interfaces are not really the same.

Here's a TS Playground to play with

P.S. I browsed through a few SO questions, including this one about arrow function vs. normal function inside interface but none of them gave the answer to my problem.

const arrowAcceptingString = (str: string) => "some string";
function functionAcceptingString(str: string) { return str[0] ?? "some string"; }

interface MethodCanHandleStringOrUndefined{
    handleText(text: string | undefined): string;
}

interface ArrowCanHandleStringOrUndefined {
    handleText: (text: string | undefined) => string;
}

// (1) should be TS error -- `functionAcceptingString` can't handle `string | undefined`
const testMethod: MethodCanHandleStringOrUndefined = {
    handleText: functionAcceptingString
}

// (2) Correct TS error ✅
const testArrowFunction: ArrowCanHandleStringOrUndefined = {
    handleText: arrowAcceptingString,
}


// (3) should be TS error -- `arrowAcceptingString` can't handle `string | undefined`
const testArrowToMethod : MethodCanHandleStringOrUndefined = {
    handleText: arrowAcceptingString
}

testMethod.handleText(undefined); // failing in runtime
testArrowToMethod.handleText(undefined); // failing in runtime
so_close
  • 318
  • 1
  • 8
  • The issue is that with `--strictFunctionTypes` enabled, non-method function types (such as arrow functions) are checked properly, with contravariant parameter types. But methods are always checked with *bivariant* parameter types, meaning it accepts both safe (contravariant) calls, and unsafe (covariant) calls. See the answers to the linked questions for more information (and specifically look for words like "bivariant" and "strictFunctionTypes") – jcalz Oct 02 '22 at 23:42
  • Note that in the title you're using the term "false positive" where I would use "false negative". A compiler warning is a *positive* result (the presence of a bug) while the absence of a warning is a *negative* result (the absence of a bug). If the compiler misses a bug and doesn't emit an error, that's a false negative. If the compiler catches a bug that isn't actually present, that's a false positive. – jcalz Oct 02 '22 at 23:45
  • Hi @jcalz! Thanks a lot for your comment, and correcting me on "false positive"-ness. So, are you saying that in TS, there's no way to force methods to only be checked for safe calls? I understand this is an intentional decision, which probably has some reasoning behind it. If so, where could I learn about that reasoning? – so_close Oct 20 '22 at 14:06
  • You can read [here](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html#strict-function-types) or [here](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-function-parameters-bivariant) or other places, most of which are mentioned in the linked questions/answers above – jcalz Oct 21 '22 at 00:05

0 Answers0