-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TS2367: This condition will always return 'false' since the types 'Constructor<T>' and 'typeof Child' have no overlap. #27910
Comments
The presence of an error is working as intended, as per the issue you cited (#25642), because neither The one thing we could do here is improve the error message to avoid the false claim that the condition will always return false. Along the lines of #25541, shall we say something like the following?
|
Thanks for the explanation. Yes, that error message would be more helpful. |
Can I take this up? |
Wait, If This is inconsistent behaviour. It should either produce error in both cases or in none of them. By the way, the old message was not ambiguous, the inconsistency was. However there are even more inconsistencies:
declare type Constructor<T> = new (data: T) => Base<any> then the comparison operator does NOT produce error.
class Child extends Base<any> {
constructor(public data: any) { super() }
} then the comparison operator does NOT produce error. So if the parametrized type is Having said all above - I guess there is some deeper problem - so it should not marked as "good first issue"). |
@moccaplusplus However, in this case, the compiler sees a comparison that looks like comparing a The root cause of that, in turn, is that a type parameter behaves as if it were an arbitrary subtype of itself, because during an actual call the type parameter will be instantiated with some subtype but we can't say which -- this is why you can't return a |
@RyanCavanaugh It is incosistent. ;) Proof: Let's introduce function: function constrEquals<T>(c1: Constructor<T>, c2: Constructor<T>): boolean {
return c1 === c2;
} then function func<T>(constructor: Constructor<T>): void {
constrEquals(constructor, Child); // No Error
constructor === Child; // ERROR
} |
Having different code behave differently is why some code produces errors and some doesn't. It'd be unfortunate if all inputs to the type system had to agree to all produce an error or all not produce an error. Your example is similar to |
I just realized inconsistency was due to the fact that When it is not - then it's consistent: function func<T>(constructor: Constructor<T>): void {
constrEquals(constructor, Child); // ERROR
constructor === Child; // ERROR
} the call: adding some properties to |
This looks like the same problem, and I'm honestly baffled by it. The comparison can be true, so I don't understand why it should error at all regardless of the message. The comparison is asking "is I've run into this checking for a sentinel value that is intentionally an instance of a subclass of the type parameter. This behavior prevents checking for sentinel values in this way without reasserting a fact we already know: the sentinel value must be assignable to |
I feel like this should work given that function fn<T>(t: T) {
return t === '' // error
} Not sure why, but this works function fn<T extends unknown>(t: T) {
return t === '' // works
} Should I create a different issue @sandersn? Maybe all unconstrained generics should extends |
its work |
TypeScript Version: 3.2.0-dev.20181011
Search Terms: TS2367
Code
Expected behavior:
Compiles without errors.
Actual behavior:
Playground Link
Related Issues: #25642
The text was updated successfully, but these errors were encountered: