Skip to content
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

Handle Java generics cases better, emit more strict TS generics #49

Open
niloc132 opened this issue Feb 27, 2023 · 0 comments
Open

Handle Java generics cases better, emit more strict TS generics #49

niloc132 opened this issue Feb 27, 2023 · 0 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@niloc132
Copy link
Member

Java arrays are covariant/contravarient, but Java generics are not. This plugs this particular bug:

Number[] numbers = new BigInteger[] { new BigInteger(1), null };

numbers[1]  = (Integer) 1;

The cast in the last line isn't necessary, but just to illustrate the point - we're asking Java to put a Integer in an array only meant for BigIntegers. In contrast, consider how a list would look if you tried to make it more generic:

List<? extends Number> numbers = Array.asList(new BigInteger(1));

numbers.add((Integer) 1);//compile error!

This time the compiler catches us, and tells us we're wrong, because while BigInteger and Integer both satisfy ? extends Number, by the time we get to the second line, we don't know which subtype of Number actually should match the wildcard - that's what the wildcard is supposed to mean.

This also won't work, and will fail on the first line, no need to even try the second:

List<Number> numbers = Arrays.asList(new BigInteger(1));

On the other hand, over in TypeScript, generics are covariant/contravarient, you can "upcast" and illegally widen a type, such that the original producer of this object can no longer actually use it in a type safe way. This is super easy to demonstrate:
https://www.typescriptlang.org/play?#code/MYGwhgzhAEBiD29oG8CwAoaXoDswFsBTALggBcAnASxwHMBuDbaYeHcigV2DPgoAo8RUpRq0AlCiYBIZmQAWVCADohhaAF5cBQo0zYAvhiPpQkGACEwFaIQAeZQjgAmMBEjTppYWiRyd8ACNCCj1pVnZKbl4BNRFqOgAaaB8-AOCKSU9paQhOAAcQwR1xMOkFJWVUzRTfMJMTMyg4RABhNjIwGhCpLwB6PpYwHBYOrpH3FJdoKwoMbwoKMABPYgBBRZWAHncAPnmIjmi+fiz58sUVayXlmoBtAF16g-lCYABrU+IAN3gqZ16OQqV02y2UADM+ABRMDAeT8eCBABWml2gJyh3gIEIyhA8FoCORqhKZWkA0x2Nx+MJSKqvnEA3kYG+6l40Ec5GgVHBM2s7KQEEI6m50AA7upgMNoM4kMDlPLzgZxPMTMYME1LNZ2jhOt0bPZHC43G0xnrAQMhiM2CBbhFdSNZskcIQWTZ3PNrit1qCtrN9l5DlEeCczl5cgUiqVznLPbctI9nmG4W9PuIfn8AdkLpVYxDobD4YiURo0VnwmwIFicXiCUXiUQo2Hy+wq1Ta0TUgzBvhOJz7EoyMlApwyGKqCAQGLqI5oAAiTguQjg7rOWfJF1OdnyeCcWjyWoS4Y4eCj4LQBfOJcrgCEiuVXgaGAw4IXPCobBSzmc-GAxHc2vtEJQ3CKpQWUfJe3hZ1RRaeB+AAckgZxwXg8R70aCtRztcYei0aDeQoACcIERswC-H9TWdTJ1UokJlGTD5TiAA

Based on https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#optional-variance-annotations-for-type-parameters, I believe that the default generics emitted by this tool should translate <SomeType> in Java into <in out SomeType> in TS, to make it invariant. In turn, <? extends SomeType> should be <out SomeType>, and <? super SomeType> should be <in SomeType>. Following this guidance, it should never be possible to emit <SomeType> in any TS from Java.

As a short term, test fix, we can probably just transition from <SomeType> to <in out SomeType>, to make all generated generics invariant, and then work our way back to closer semantics for Java PECS.

@niloc132 niloc132 added this to the 1.0.0 milestone Mar 21, 2023
@vegegoku vegegoku self-assigned this Mar 22, 2023
@vegegoku vegegoku added the enhancement New feature or request label Mar 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants