Open falsandtru opened 5 years ago
Note that a regression test for #30118 is already added but another case, posted here and there, is not covered by it.
Can't reproduce on 3.5.0-dev
- is this behaviour in a release branch or at some intermediate point?
Can you try with 3.5.0-dev.20190504?
ping @weswigham
Just tried off master and I do get the error you link.
I presume you are running strictFunctionTypes
?
This error looks correct to me [EDIT: for this specific example, but there may be something wrong for other examples. See next comment in thread]. The property instances
is a set of Supervisor<string, unknown, unknown>
, therefore allowing the method call
to accept arguments of type string
in the name
position. The this
instance is generic in the name
parameter to call
and may be instantiated with something more specific like "a"
, so it's not safe to assign this
to Supervisor<string, unknown, unknown>
.
A smaller example:
declare let withString: Supervisor<string>;
declare let withA: Supervisor<"a">;
withA.call("a", 'param'); // ok
withA.call("a string" as string, 'param'); // not ok
withString = withA; // correctly an error, otherwise we could make an illegal call through the alias
withString.call("a string" as string, 'param'); // no error
If you change call
to be:
public abstract call(name: ('' extends N ? undefined : never), param: P, timeout?: number): Promise<R>;
you still get the error, which is probably incorrect and due to an invariant variance calculation which has been turned on again for the conditional type extends type. Small repro:
interface A<T> {
x: number extends T ? 1 : 1;
}
declare let a: A<number>;
declare let b: A<3>;
a = b; // error
b = a; // error
@weswigham Is it worth using your new unmeasurable markers for this?
// Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if
// one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2,
// and Y1 is related to Y2.
const u1 = instantiateType((<ConditionalType>source).extendsType, reportUnmeasurableMarkers);
const u2 = instantiateType((<ConditionalType>target).extendsType, reportUnmeasurableMarkers);
if (isTypeIdenticalTo(u1, u2) &&
...
I presume you are running strictFunctionTypes?
No: https://github.com/falsandtru/spica/blob/master/tsconfig.json
declare let withString: Supervisor
; declare let withA: Supervisor<"a">; withA.call("a", 'param'); // ok withA.call("a string" as string, 'param'); // not ok withString = withA; // correctly an error, otherwise we could make an illegal call through the alias withString.call("a string" as string, 'param'); // no error
TypeScript originally hasn't supported this problem as Arrays also have the same problem. Therefore type checking is wrong or wrongly too strict in this case. So the error message may be correct but TypeScript shouldn't check it.
interface A
{ x: number extends T ? 1 : 1; } declare let a: A
; declare let b: A<3>; a = b; // error b = a; // error
Does it also fix this issue?
Yep a couple of things wrong in my comments. Corrections:
strictFunctionTypes
is irrelevant here because call
is a method.withString = withA; // correctly an error, otherwise we could make an illegal call through the alias
is not relevant because call
is a method. It would be an error if call
was an arrow function, but it's not and so should not error for your code.
Does it also fix this issue?
The minor suggestion I posted does fix my small repro and your example - though I'm not sure if it's the correct thing to do overall.
@ahejlsberg Take a look?
@ahejlsberg Can you also fix this regression?
The similar problem #30118 had been fixed, but appeared again.
TypeScript Version: 3.4.0-dev.20190504
Search Terms:
Code
Expected behavior:
pass
Actual behavior:
Playground Link:
Related Issues: