Allow as precompiled type cast for type inference
vaderkos opened this issue · 2 comments
Search Terms
runtime const infer inference compile pre dynamic type as
Suggestion
Let known variable types be precompiled to infer types using special cast as precompiled
It would be very helpful in type inference of dynamic code that is generated in runtime but has all types known statically
Example
Now type may be inferred for some variables that have very basic types
const arr1 = [1, 2, 3] // => type is **number[]**
const arr2 = [1, 2, 3] as const // => type is **[1, 2, 3]**
const str1 = 'hello' // => type is **string**
const str2 = 'hello' as const // => type is **'hello'**
But what if we do not want to write types for something that is generated from everything known before compilation
const arr1 = 'A, B, C'.split(',').map(str => string.trim()) // type is **'string[]'**
const arr2 = 'A, B, C'.split(',').map(str => string.trim()) as const // => **now it's Error**
const arr3 = 'A,B,C'.split(',').map(str => string.trim()) as precompiled // => **type is ['A', 'B', 'C']**
Also same feature can be used inside function so proper type inference may be used
That would allow route params type infer
const getPathParamsGetter = (routePattern) => {
const indexes = routePattern
.split('/')
.map(r => r.trim())
.filter(r => r.length)
.reduce((acc, part, index) => {
if (part.startsWith(':')) {
acc[index] = part.slice(1)
}
return acc
}, {}) as precomiled
return (path: string) => path
.split('/')
.map(r => r.trim())
.filter(r => r.length)
.reduce((acc, param, index) => {
if (indexes.hasOwnProperty(index)) {
acc[indexes[index]] = param
}
return acc
}, {})
}
// Under the hood we have
// So here the code is executed and then as const is applied
req.params = getPathParamsGetter('/:model/:id')(path) as precompiled
app.get('/:model/:id', function (req, res) {
const { params } = req /* So here we have params type { model: string, id: string } */
res.json(params);
});
It only should work when all variables for pre-compilation are known and do not emit any runtime code, only static type checking but with some dynamic features.
Overall feature sound like, run the code if everything is statically known and than cast the result with as const
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of [TypeScript's Design Goals]
Executing user code during compilation time is the first step toward madness; we don't implement features like this and don't intend to.
@RyanCavanaugh how I wish you could be in the trenches with us working on apps where you would benefit from being able to fully type check API boundaries;
experiencing the awkwardness of maintaining codegen tools that keep TS type defs in sync with things like GraphQL, JSON schemas, etc;
accidentally OOMing the compiler when you try to make fancy type magic for computing the exact response type for a REST route from Zod schemas, taking into account up to 4 levels of associated entity inclusion in the request; all because your boss hopes that can be accomplished, and you agree it would be awesome if possible --
only then would you truly understand how desirable this is. We are already deep within the madness. The madness is trying to execute ever-more-complex TypeScript type logic during compilation without exceeding its limits. For us, having a more powerful, flexible form of computation we can perform during compilation feels like the only way out of the madness.