-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
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.