-
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
Generic lambda identity function can cheat typesystem easily #8397
Comments
(I'm using version Hi, I tried to rewrite the example a bit differently: This errors: let func: <T>(a: T): T => "abcd"; // error: string is not assignable to T However when the signature is declared separately, as a type. This invalid return type can be 'hidden' under the declared type, as the call signature type type Func = <T>(a : T) => T;
let func: Func = <T>(a: T): string => "abcd"; // no error And then a caller can use any type for let x = func(1234); // 'x' gets type 'number' but the actual value "abcd". It looks as if the compiler considers these function types compatible, in particular the return type I'll try to isolate and rewrite it as clearly as possible: type Func1 = <T>(a: T) => T;
type Func2 = <T>(a: T) => string;
let func1: Func1;
let func2: Func2;
func1 = func2; // no error And compare it to: type Func1 = <T>(a: T) => number;
type Func2 = <T>(a: T) => string;
let func1: Func1;
let func2: Func2;
func1 = func2; // error: type 'string' is not assignable to 'number' I'm aware that function parameters are bivariant, and based on my tests function return types should be covariant. I'm not sure if that has anything to do with this though. There isn't much further information I can provide at this point. |
Further investigation: #3410 includes some information (although almost a year old), explaining this check (or a related one, I'm not sure) is avoided to due performance reasons. Seems like almost any function can be assigned from or to a generic signature. Parameters and the return type are considered to be of type declare let func1: <T, V>(a: T, b: V, c: V) => T;
declare let func2: (a: number, b: string, c: void) => void;
func1 = func2; // no error |
I'm not sure, if this should be looked in this issue, but currently TypeScript also doesn't look on generic type constraints when it check functions types:
|
Unfortunately signatures are seen in their "erased" form (with type parameters replaced with their constraints) during assignability checks. This is something we're aware of as a hole but don't yet have a solution that gives satisfactory performance, |
@RyanCavanaugh if performance is a problem (presumably due to recursive deep dives) why not limit checks to a certain depth that can be configured from tsconfig.json, who don't care about typesafety sets "depth: 0" and production ready builds "depth: 100"? |
tracked by #5616 |
Hi. Before I start I want to emphasize that I googled a lot for that problem and found nothing. That being said, my problem seems to be so simple, that I am sure it was discussed before. If that is the case forgive me for spam. I would be just grateful for some link to the explanation of why TS works here the way it works.
I use TypeScript 1.8.10
So... this does not compile (which is good):
This however DOES (which for me seems super bad):
The text was updated successfully, but these errors were encountered: