-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Better Type Inference #1812
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
Comments
I like the idea; I think this could be cleaner and more powerful if it made use of the TS 4.x improvements to Tuples, variadic types, and generic types. Been meaning to take a crack at doing this to Map for a while; I prefer HM-style types, so recursion and type-algebraic shenanigans feel a little more natural. 🤷 |
yeah, this solution worked well and fixed my problems for type inference, but there is problems in this implementation, the first one is that the |
I think there is a huge problem with the actual Map interface. interface Map<K, V> extends Collection.Keyed<K, V> That is blocking a lot of things as it dissociate the keys and the values. It is useful as a Map is a I started working on a different implementation for Map that are objects that might address these issues (still work in progress) interface ObjectLikeMap<R extends {[key in string|number]: unknown}, K extends keyof R, V extends R[K]> extends Map<K, V> {
get(index: K, notSetValue: never): R[K];
get(index: K): R[K];
} |
@jdeniau so, there is a problem on your implementation, as I said, it will not work for deep nested objects, for and example, if for some reason you have const user = { name: 'name', profile: { role: 'user' } }; and a interface like this interface User {
name: string;
profile: { role: string };
} so what will happens when you put it into a |
@EduardoAraujoB Yes, |
We are working on Map in #1841 |
thanks a lot @jdeniau I will check it out the progress and see if I can help |
Immutable js types have many flows (I mentioned one of them at #1884 ). Overall using immutable.js in typescript is a nightmare because of constant type issues that are not always consistent between nodejs and browser based typescripts! I am considering moving away from it unless types will be improved. |
@antonkulaga you can just read the last two comments and you may find an open PR that tries to solve some issues with Map in TS... You already opened two issues about TS. No need to be pushy with two comments on another issue mentioning yours. immutable-js is open source work. All the maintainers take on their free time to work on this (for example it's Sunday morning and I'm replying to you). About the "threat" about not using immutable anymore: we don't owe you anything, so if you are not helping or enjoying immutable, please do use another alternative. If you want to help though, you can :
Thank you |
Personally I found immutable unusable due to the inability to narrow unions of Map types but I think this is more a limitation of both typescript and javascript art this time. type Field = "String"|"Number"|{List:Field}|{Choice:Set<Field>}
```But converting this to immutible required the use of Map which couldn't be effectively discriminated against for the List and Choice variants.
This type was coming from auto generated API schemas so couldn't really be changed unfortunately.
If anyone knows how to do this without a bunch of flaky and case specific guard types I'm happy to implement it.
Proxies could maybe do it but given they're not being used already I assume the project has good reason to avoid them? |
@Isaac-Leonard can you try the v5 RC? A lot of change has been made to the |
Running 6pm install immutable gives me the v5 beta.4, I assume that's the most recent release? export type Field =
| "String"
| "Number"
| { List: Field }
| { Choice: Set<Field> };
type P = FromJS<Field>;
let x: P = "String" as P;
if (typeof x !== "string") {
x.has();
} The call to .has doesn't work as it is the argument is typed as Never because of the union of the two map types. |
Another issue is that the get method can return undefined even if the original objects properties are not typed as undefined. |
I think that the FromJS of a union lost TS here. Immutable 5 latest change improve the Map type and introduced I see you do export this type but I think I would have done this :
This way your if should know that this a Map or a Map and that has should work. |
I can't seem to make it work properly.
Works fine but assigning a value from fromJs() to a variable of type Immutable field doesn't work due to the differences between MapOf and Map. I also can't get any methods to work on it:
Just gives a error about has not being a field on test2 and it seems as though test2 has no fields or methods. |
@Isaac-Leonard it's because you did not type The But you are right, pushing this forward (ts playgroud link), there is a issue of the union of I'm keeping that in mind if I have a fix in the future. |
Problem
So, let's suppose that you created a variable in this way
const user = fromJS({ profile: { name: 'username' } });
, so the main problem in that this variable has a typeany
which makes harder to find what this variable really is, one example is if someone just make a shadowing in that constant using thetoJS()
method, that will cause a lot of errors and things will get harder to know what type it has.There is also another problem, which is to infer the types of subarrays and subobjects (like the name inside the profile), which will requires recursive type, something reeaaly weird to do
My local fix
Note: this solution is a huge hack and could cause troubles in the type system, keep that in mind
So to infer the types in a recursive way for objects (keeping the same type for all the rest), here is a huge hack that I made and fixed the type inference problem for me
this solution doesn't not cover everything, but fixed my problem and if something is missing, I can just add it
The text was updated successfully, but these errors were encountered: