Description
TypeScript Version: 3.8.0-dev.20200118
Search Terms:
variance contravariance covariance
Code
class Success<T, E> {
constructor(readonly value: T) { };
public isSuccess(): this is Failure<T, E> {
return true;
}
}
class Failure<T, E> {
constructor(readonly error: E) { };
public isSuccess(): this is Success<T, E> {
return false;
}
}
type Result<T, E> = Success<T, E> | Failure<T, E>;
function Test(n: Number): Result<number, Error> {
return new Success("test");
}
Expected behavior:
Expected error:
Type 'Success<string, Error>' is not assignable to type 'Result<number, Error>'.
Type 'Success<string, Error>' is not assignable to type 'Success<number, Error>'.
Type 'string' is not assignable to type 'number'
Actual behavior:
No error
The code is part of an attempt to create a result object pattern in TS.
Through some bisection I have managed to narrow this down to 1a10e71
It appears this was considered an error up to that commit.
I have tried my luck in understanding the that PR but at the moment sadly I am unable to fully understand it
.
I was able to make the code correctly (assuming it is correct behavior) display the error by referencing both T and E in Success and Error respectively a-la:
class Success<T, E> {
private _: E;
constructor(readonly value: T) { };
public isSuccess(): this is Failure<T, E> {
return true;
}
}
class Failure<T, E> {
private _: T;
constructor(readonly error: E) { };
public isSuccess(): this is Success<T, E> {
return false;
}
}
Trying to read the PR I assumed this was some how related to recursiveness of the types but again fully understanding it alludes me.
Another thing that alludes me is that if add the following code (which I understand is an error on its own):
declare class Success<T,E> {
constructor(readonly value: T);
}
The expected behavior seemed to occur, I attempted this after being baffled as to why using an existing behavior (https://github.com/gDelgado14/neverthrow) yielded the expected behavior and my attempts at copying the library's code verbatim into my code did not.
If this indeed intended behavior I would love nothing more than to understand why is it so and how the aforementioned commit lead to it as I failed to deduce it on my own
Playground Link: Playground Link
Related Issues: #37400