unsplash / sum-types

Safe, ergonomic, non-generic sum types in TypeScript.
https://unsplash.github.io/sum-types/
MIT License
42 stars 2 forks source link

TS language server features for sum type members (e.g. rename) #10

Open OliverJAsh opened 3 years ago

OliverJAsh commented 3 years ago

Slack discussion for reference: https://crewlabs.slack.com/archives/CFZE45NTW/p1631709631008600

With Unionize it was very easy to rename a tag in the union—TS would propagate the change to all constructors, match functions and type definitions. Can we achieve something close to this?

https://user-images.githubusercontent.com/921609/133125412-0fbee27b-c4e2-445f-80ed-f499ceb60771.mov

OliverJAsh commented 3 years ago

Unfortunately I doubt this will be possible.

Renaming works if we define the union first as a record and pass that record around (i.e. the way Unionize works):

type MyRecord = { A: string; B: string };
type Constructors<T> = { [K in keyof T]: () => void };
declare const constructors: Constructors<MyRecord>;
constructors.A();

However it doesn't work if we define a union manually:

type MyUnion = { tag: 'A'; value: string } | { tag: 'B'; value: number };
type Constructors<T extends { tag: string; value: unknown }> = {
    [K in T as K['tag']]: () => void;
};
declare const constructors: Constructors<MyUnion>;
constructors.A();

It seems that renaming only works when you use K in keyof T in a mapped type, not when you do K in T as K['tag'] or K in T['tag'].

OliverJAsh commented 3 years ago

Potentially related TS issues:

🤞 Hopefully it will be fixed in TS soon.

OliverJAsh commented 1 year ago

This is a wider issue than just renaming. It also affects other language server features such as "go to definition" and "find references". Example of go to definition from my reduced test case above:

image