Approach6: infer TS from JS template literal #7
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
⚠️ Warning: this experiment can potentially drag us in another TypeScript rabbit-hole ⚠️
@glen in the branch
approach6_infer_js_to_ts
, I've created a fileinfer.ts
with an experiment with a totally different approach:https://code.studioinfinity.org/glen/typocomath/src/branch/approach6_infer_js_to_ts/src/infer.ts
It's very experimental. My idea is: take the pocomath JavaScript template string and generate TypeScript types from that (inspired by typed-function #123).
If this works out:
typescript-rtti
But:
multiply: '(T, T) => T'
I think this is worth a bit more fiddling to see if the issues are solvable or not, but we should be careful spending too much time if this is not feasible.
What do you think?
Isn't this basically what m93a tried initially in his typed-function proof-of-concept? (Sorry I'm feeling too lazy at the moment to look up the link to that for you) I was against that at the time, immediately because there was a redundancy between the typed-function-style annotation and the type that TypeScript should infer from the implementation code itself. Now that I've despaired of actually getting those types to work for us (specifically because of generics), and so we are declaring interfaces and then just having TypeScript verify compliance with them, the repetition here is no worse. You might look back at the discussion with m93a and see if it surfaced any other concerns. Certainly handling generics is one. The other is that it seems a little weird to be devising and implementing a little language for specifying types of things, when TypeScript, that we're planning to use for this next revision of the code, already has such a language built in to it. So why not use that language for the specification and then just extract the information from it that we need? And doesn't the TypeScript mechanism for going from the strings to types use the kind of complicated type-manipulation stuff you've been hoping to avoid? Finally, it looks like the above notation will reiterate the return types on every usage, which I'd certainly prefer to avoid.
So I definitely don't mean to dissuade you from trying to make this work more nicely if you think it's promising, just saying it isn't immediately drawing me in to work on this direction. As far as I am concerned, approach 4.5 is currently the "prototype to beat," so to speak.
Yes, go do Christmas! ;-) See you in a while.
This is a bit of the "opposite" of what we tried in #123: there, we where trying to make
typed(...)
return a full-fledged TS interface. In this experiment #7, I try to generate a TS interface from an injected dependency, which is "just" inferring a TS type from a string like(number, number) => number
for each key in a given object. It would not introduce a new language, but "just" use the little language thatpocomath
(JS) uses to describe a signature.At this point I do not think we should pursue this approach (TS rabbithole danger), but still, it would be awesome.
OK, given your sentiments above and the results of our conversation today, I am closing this issue.
I gave the template literal type another go. I found a stackoverflow answer that helped a lot, and now the solution works with multiple dependencies and defining the sigature of the function that is being created. The following example is fully typed. See source code of src/infer.js.
@glen this still looks interesting. I'm still not sure if it is feasible in the end though. I want to see if I can get generics to work too, and get the API in a shape more similar to the one in
main
.Congrats on getting this to compile and type correctly. Reopening this issue.
I think you know I still have the concerns that this approach will (a) require us to re-implement a portion of the TypeScript type specification language (or worse a subtle variation thereof), which opens up a syncing issue if there are any changes to the underlying language, and just seems like re-doing work that has already been done, and (b) be more redundant than the compiler-plugin based solutions, e.g. above you've said twice that multiply takes two numbers, once in
const Multiply = 'multiply(number, number) => number'
and again inconst multiply (a: number, b: number) => a*b
. Plus there are three occurrences of [Mm]ultiply in the code, which seem redundant. Maybe some of these redundancies could be eliminated with some refactoring, but I remain worried.All that said, if this is the direction you want to go for strictly TypeScript-typing "mathjsNext" code, I'm looking forward to moving the project ahead via any coherent typing strategy. So I remain on standby to put in effort once the typing strategy is determined. Thanks!
Well, I still have large concerns here too. It requires a lot of effort to get something working, and we still have a lot to figure out.
Next steps are defining interfaces as strings like
{ multiply: '(T,T)=>T', square: '(T)=>T' }
, and then use these interfaces likeDependency<'multiply', number>
. Then it would be quite close to the syntax we settled on in themain
branch.I would love this to work out, but right now I think this approach is to fragile and inflexible (if we get all of it to work in the first place).
I'll close this issue again, we're not actively working on this approach and not planning for that either.