# "Correlated Union Types" https://github.com/microsoft/TypeScript/issues/30581 ```ts type NumberRecord = { kind: "n", v: number, f: (v: number) => void }; type StringRecord = { kind: "s", v: string, f: (v: string) => void }; type BooleanRecord = { kind: "b", v: boolean, f: (v: boolean) => void }; type UnionRecord = NumberRecord | StringRecord | BooleanRecord; function processRecord(record: UnionRecord) { record.f(record.v); // error! // error msg in TS3.2 and below: can't call union of functions // error msg in TS3.3 and up: record.v not assignable to never } ``` * We want to be able to feed the callback with the original value; but now `v` is a union type and `f`'s parameter type is an intersection; that's not precise for `v`, and that intersection now only accepts `never`. * People have speculated that maybe we need existential types so that we can say "this function takes whatever type `v` has" and can feed it through. * Can try to re-model this in the form of a re-indexed mapped type. ```ts interface TypeMap { "n": number; "s": string; "b": boolean; } type UnionRecord<P extends keyof TypeMap> = { [K in P}]: { kind: K; v: TypeMap[K]; f: (p: TypeMap[K]) => void; } }[K]; function processRecord<K extends keyof TypeMap>(record: UnionRecord<K>) { record.f(record.v); } ``` * With some improvements of inference and apparent types, we can enable most of these cases - 2 improvements on the scale of what feel like bug fixes. * First is inference to the IIFE-like mapped object pattern from above. * Second is how we present the apparent members of certain types when you index into an already-instantiated mapped object type (a "table type") with some generic key. * `{ [P in K]: Foo<P> }[X] => Foo<X>` * Does that mean that if you *aren't* using a type that was declared as a mapped type, then we won't get a more precise type? * Yes, if you leave off types on these objects. * I guess we don't have an easy way to correlate. * We could *try* to do something there...but that's a bit of a stretch. * This is a weird pattern. Would like to not have to teach people to write this. # Modules Migration Status Update https://github.com/microsoft/TypeScript/pull/46567 * A lot of time running tests. * A lot of time is going into getters for every single binding. * Had TypeScript generate to CJS, had esbuild run on top of that. * Swapped TS to generate ESM, and esbuild generates the same sorts of bindings - so no optimization there. * 25 minutes to run the full tests! Thanks to the multiple levels of indirections of calling functions. * Could switch to ES3 emit to avoid accessors. * Also could switch to native ESM emit. * No telling how slow ESM live bindings would be. * Could avoid indirect barrel imports. * Looked at bundler front-ends that are largely esbuild wrappers. * But these tend to push for the optimized build to use Rollup. * \[\[Whole discussion on what the right shipping format and layout to send.]] * Dogfooding with modules showed us just how slow this is. * Even getting complaints on tslib: https://github.com/microsoft/tslib/issues/165 * Conclusion * Investigate the `__createBindings` issue. * Investigate alternative bundlers. # Ensuring Modules Conform to a Type https://github.com/microsoft/TypeScript/issues/38511 * Lots of people would like to be able to ensure "this file has this sort of shape." * Then "I would like this folder to describe this shape". * `export implements SomeType` that * PR suggests everything should be contextually typed. * You can emulate this today with a self-import. * Without contextual typing, this is possibly just sugar that saves you 2 lines. Maybe not as compelling. * This links to typing default exports - is that the real feature? * Out of time - revisit in the new year.