1

Why does the same set of overload signatures for the same function work fine when the function is a class method, but not when it's defined as a plain function at module toplevel?

interface Foo {
    bar: number;
    baz: string;
    bat: boolean;
}

function cleanFoo({bar, baz, bat}: Foo): Foo {
    return {bar, baz, bat}
}

function cleanFooPartial({bar, baz, bat}: Partial<Foo>): Partial<Foo> {
    return {bar, baz, bat}
}

class FooCleaner {
    cleanFooOverload(foo: Foo): Foo;
    cleanFooOverload(foo: Partial<Foo>): Partial<Foo>;
    cleanFooOverload({bar, baz, bat}: Foo): Foo {
        return {bar, baz, bat}
    }
}

function cleanFooOverload(foo: Foo): Foo;
function cleanFooOverload(foo: Partial<Foo>): Partial<Foo>;
function cleanFooOverload({bar, baz, bat} : Foo): Foo {
    return {bar, baz, bat}
}

cleanFoo is the primary version; cleanFooPartial is to show that the same implementation matches the overload that takes and returns a Partial<Foo>; FooCleaner.cleanFooOverload works fine.

Why does the toplevel definition report this error?

Overload signature is not compatible with function implementation.

millimoose
  • 39,073
  • 9
  • 82
  • 134
  • I can tell you why it happens but I am not sure if it's a big or not. If you disable `strictFunctionTypes` the error goes away. Class methods are not impacted by `strictFunctionTypes` this is why one raises an error and the other does not (https://stackoverflow.com/questions/52667959/what-is-the-purpose-of-bivariancehack-in-typescript-types/52668133#52668133) – Titian Cernicova-Dragomir Feb 15 '19 at 01:38
  • 2
    The implementation signature should accept `Partial` and not require `Foo`. The class method doesn't error because it accepts bivariant parameters even with [`--strictFunctionTypes`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html#strict-function-types) enabled, but bivariant parameters aren't type safe. – jcalz Feb 15 '19 at 01:43
  • @jcalz I don't quite want to do that; if I add a new property to `Foo`, I *want* the implementation to report an error until I include it there. Making the function `Partial => Partial` loses that check. – millimoose Feb 15 '19 at 01:47
  • How to do this in a type safe way would I suppose be the actual question here. Except I already asked that question yesterday and got the bivariant overload as an answer on it: https://stackoverflow.com/questions/54634788/is-there-a-type-safe-way-to-express-that-a-function-returns-an-object-of-type-t – millimoose Feb 15 '19 at 01:54
  • 1
    So.. maybe make the implementation signature accept a `Partial` but return a `{ [K in keyof Foo]: Foo[K] | undefined }` (which is *like* `Partial` except it explicitly claims to return an object with all the keys even if their values might be `undefined`). – jcalz Feb 15 '19 at 02:00

0 Answers0