Skip to content
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

Type Safety for Superfine Source Code Through JSDoc Types. #145

Closed
rbiggs opened this issue Jul 11, 2018 · 14 comments
Closed

Type Safety for Superfine Source Code Through JSDoc Types. #145

rbiggs opened this issue Jul 11, 2018 · 14 comments
Labels
discussion types Strings, numbers, booleans

Comments

@rbiggs
Copy link

rbiggs commented Jul 11, 2018

I made a fork of Superfine with full type safety for Superfine source code using only JSDoc: https://github.com/rbiggs/superfine/tree/JSDoc This gives you full intellisense, code completion, live type checking, etc. in the source code as JavaScript. Just set your user preferences in VSCode to:

"javascript.implicitProjectConfig.checkJs": true

Then examine the source code in VSCode. This lets you write plain ole JavaScript with all the benefits of typed TypeScript.

Because JSDoc comments are valid JavaScript comments, they do not affect the final output of the source code during build time. The JSDoc comments get removed during minification. Using types in the source code does require escaping expando properties with [""], but these also get removed during minification.

This provides custom types for VNode, etc., and type casting to resolve static type checking's inability to force type casting that occurs during runtime in the browser. The cast item requires extra parens around it to signal that it is being cast, but these get removed during minification as well.

@jorgebucaran
Copy link
Owner

@rbiggs Nice job! Why add jsdoc comments to non-exported functions?

@rbiggs
Copy link
Author

rbiggs commented Jul 12, 2018

Basically, the same reason one would write Superfine in TypeScript--type safety for the entire code base. With that in place, incorrect use of types in the source code will show up immediately. Besides, some people, myself particularly, like to import source files instead of distribution files to work with. I let my build pipe line handle the bundling and minification. An external d.ts file only describes what the external public interface is, but doesn't ensure that anything internal is correctly typed.

In #134 you mentioned a possible rewrite in TypeScript. I'm assuming for type correctness. This gives you the same thing while keeping it JavaScript. No need for a build step to convert it to JavaScript. It's already the JavaScript you want, but with types.

@brodycj
Copy link

brodycj commented Jul 12, 2018

In #134 you mentioned a possible rewrite in TypeScript. I'm assuming for type correctness. This gives you the same thing while keeping it JavaScript.

+1 (+100)

I would personally favor adding a couple more "scripts" to package.json to check the code even further:

@jorgebucaran
Copy link
Owner

Thank you, both! JSDoc looks promising, but I'm seriously considering to rewrite Superfine in TS.

@rbiggs
Copy link
Author

rbiggs commented Jul 12, 2018

Having done a lot of TypeScript in the past doing DOM manipulation, converting Superfine, and in particular, patchElement will be a lot more work than you think. TypeScript doesn't handle type coercion well because it can't foresee what the browser will do when the type needs to be coerced. I spent more time fighting to get the types right for TypeScript than writing the code I wanted to.

And TypeScript only supports a small sub set of ES6 features. I'd rather have the fuller set that Babel provides. TypeScript gave me type safety, but made me feel like I was in a straight jacket. JSDoc comments gives me type safety and lets me write the JavaScript I want.

@jorgebucaran
Copy link
Owner

jorgebucaran commented Jul 12, 2018

@rbiggs I remember porting the old picodom to TS and you are right, it took some work, but the result was less alien than I thought. Even though superfine has more code than its predecessor, I am willing to bet it will be simpler because as you've seen, the vnode props are stricter than before, e.g., strings no longer represent TextNodes, etc.

@mindplay-dk
Copy link
Contributor

My honest perspective on JSDoc is it's just Typescript with fewer features and noisy syntax.

I keep hearing arguments like "JSDoc is just standard JS syntax" - to be accurate, it is proprietary syntax embedded in standard JS comments. You will go through the same compile/build-steps to type-check and strip the annotations, which is not very different from what the Typescript compiler does.

The JSDoc comments get removed during minification.

As do the Typescript annotations on compilation.

TypeScript only supports a small sub set of ES6 features.

It supports every ES6 feature, to my knowledge - are you thinking of something in particular?

It even supports a few experimental features and syntax in addition to standard ES6 features.

I'd rather have the fuller set that Babel provides. TypeScript gave me type safety, but made me feel like I was in a straight jacket. JSDoc comments gives me type safety and lets me write the JavaScript I want.

How long ago since you used Typescript? :-)

Granted, Typescript is a freakin' dominatrix at first - until you realize it's teaching you all good habits.

You can also specify in tsconfig.json how much punishment you're in for - personally, I like to turn it all the way up to strict, which is at times a roadblock and a PITA, but it almost always works out for the better in the end ;-)

@mindplay-dk
Copy link
Contributor

I will say though, if you write a lot of pre-minified/mangled code, strict mode won't make your day - mostly the compiler and syntax is optimized for plain, idiomatic, readable code and often does not take kindly to your little hacks or heavily leaning on Javascript quirks.

I am personally happy to forego those habits and take on a few extra bytes. YMMV.

@rbiggs
Copy link
Author

rbiggs commented Jul 12, 2018

Microsoft uses JSDoc comments to create richer intellisense for TypeScript. All the d.ts files they provide with TypeScript have JSDoc comments. Heck, event the superfine.d.ts file has JSDoc comments in it.

I don't have a build step for my JSDoc comments. They get used while coding using the TypeScript language service, just like it does for TypeScript files. It's just a VSCode setting to turn on. Only thing needed is minification with uglify, which automatically strips out JavaScript comments. Once in a while I might need to bundle with Rollup.

As far as the ES6 support between TypeScript and Babel, consult the Kangax compatibility table. You'll notice that for ES6 and ECMAScript2016+, Babel supports more features or more aspects of features than TypeScript does. No doubt, though, TypeScript supports more features than it did the last time I used. Which was the main reason I left it.

Any way, by habit I use type guards in my code to make sure I'm dealing with the types I'm expecting at runtime. No static type checker can prevent runtime type errors. They can only flag problems during the build. If you're using third party libraries, frameworks, plugins, widgets or third party data, only type guards can help catch and deal with type errors.

At this point, if I really wanted a typed language that compiled to JavaScript, I'd go with ReasonML.

@jorgebucaran
Copy link
Owner

jorgebucaran commented Jul 13, 2018

@mindplay-dk

bar=(foo=(a=b).foo).bar

Code like that is not pre-minified or mangled. Uglify will not generate code like that. That is just writing several lines of code on the same line. Codegolf or obfuscation are more applicable terms. I am willing to let go of these bad habits. But one at a time. I'm still a recovering addict you know. 😓

I wanted to clarify that, because you have known on occasion to mistake some of my obfuscated code for code that the minifier will produce, so one may as well use TS or whatever. This is often not the case. I know almost exactly which of my code is going to be mangled by uglify and in what way and still choose a more idiomatic variant, for example using while loops when I feel they are more readable than a half-baked for loop (which uglify will almost unequivocally generate every time).

@rbiggs
Copy link
Author

rbiggs commented Jul 13, 2018

Sorry, but I think you misunderstood what I was saying. I was not criticizing your coding style at all. I was talking about how minifiers handle JSDoc comments.

@jorgebucaran
Copy link
Owner

jorgebucaran commented Jul 13, 2018

@rbiggs No, it's okay, you can criticize it if you want. My comment was directed to @mindplay-dk.

I just wanted to clarify that some of my "deliberately obfuscated" code is how it is to compress total byte size in a way that uglify usually doesn't/can't help (maybe it's time to look into Google Closure Compiler). If uglify did all those things then there would be no point in doing them by hand myself! :)

While there's still several instances of code golf in Superfine, my primary focus has shifted to performance, with an honorable second focus on size.

@rbiggs
Copy link
Author

rbiggs commented Jul 13, 2018

Oh, my bad. 😜Any ways, I'm not gonna criticize your anything. Not my thing. I do really appreciate everything you're done so far with Hyperapp and Superfine. I've managed open source projects in the past dealing with all kinds of users. It's a thankless task. Users have no idea what library authors go through between coming up with the original idea, evolving it over time and dealing with every type of user imaginable. It's a passion like artists or musicians, except we're creating beautiful code that also impacts other people.

@rbiggs
Copy link
Author

rbiggs commented Oct 4, 2018

Closing this now.

@rbiggs rbiggs closed this as completed Oct 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion types Strings, numbers, booleans
Projects
None yet
Development

No branches or pull requests

4 participants