Skip to content

Unrelated overload signature affects inference #25917

@cartant

Description

@cartant

In fixing a problem with the typings for the RxJS first and last operators, I've stumbled across some weird behaviour with overload signatures.

TypeScript Version: next (3.1.0-dev.20180725)

Search Terms:

overload signature inference unrelated incorrect

Code

interface Foo<T> {}
interface Bar<T, S> {}

export function foo<T, S extends T>(predicate: (value: T) => value is S, defaultValue?: S): Bar<T, S>;
export function foo<T>(predicate: (value: T) => boolean, defaultValue?: T): Foo<T>;
export function foo<T>(predicate: (value: T) => boolean, defaultValue?: any): Bar<T, any> | Foo<T> {
  throw new Error('Unimplemented');
}

For the behaviour to be effected, strictFunctionTypes must be true and strictNullChecks must be false:

{
  "compilerOptions": {
    "strictFunctionTypes": true,
    "strictNullChecks": false
  },
  "files": ["index.ts"]
}

Expected behavior:

When passing a function that is not a user-defined type guard, I'd expect the inferred type to be independent of whether or not the type-guard-accepting overload signature is available or is commented out.

Actual behavior:

However, if the signature that accepts a type guard is available, the inferred type - for a call that does not involve a user-defined type guard - will be:

const predicated = foo(x => x === 's', 's'); // Foo<"s">

And if the signature that accepts a type guard is commented out, the inferred type - for a call that does not involve a user-defined type guard - will be:

const predicated = foo(x => x === 's', 's'); // Foo<string>

In RxJS, this causes a problem when the operators are used with pipe. If a return type with a string literal is inferred - e.g. MonoTypeOperatorFunction<"s"> - an error will be effected if the operators are used with a string source, as string won't be assignable to "s".

Also, why is the behaviour dependent upon the above-mentioned compiler options? In particular, why does it depend upon the strictNullChecks option?

Related Issues: None found.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions