-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
typescript checking frontend template files #5151
Comments
This is an interesting topic, but I do not have any ideas here. the main problem i see, is that the html template and the JS code that populates its context are detached, and the linkage happens dynamically. JSX on the other hand does not have this issue, as the JSX elements are evaluated in the context of their declaration. Would love to discuss ideas here on how to we can get the type checking in the html templates.. One option is to get the template compilers to generate |
Considering the easiest example, underscore's _.template function:
we should be able to decorate/extend the base function, so its contract remains the same (behaves the same way from the outside). What we want here is to make typescript compiler throw errors, when non-existent variable is accessed in the template, right? In order to do so, one option mentioned is to generate typescript code from template files. This generated code would have to rely on strict types (other than I did a quick check, that typescript's typecheck doesn't rely on inheritance, but on field names:
This means that we could parse a template, analyse what variables/structures are used there, generate disposable interfaces with optional properties (one for each template) and use them to typecheck parameters of the compiled template. For example, having following underscore template:
we could generate the disposable interface:
and use it as the type of the only input parameter of the function:
Then we decorate the template with real data. The correct invocation:
passes, while the typo one (note weathar instead of weather):
fails with following error: I think that's what we need, in general. This idea has some unsolved problems, such as how to re-use external template compiling functions (underscore, handlebars, etc) beneath, but above proof of concept works as expected in the typescript console. I didn't get the sourcemaps idea in that context (however I do know source maps in general). Does this solution require to extend typescript core (e.g. interpreting those source maps)? Hope we can figure it out somehow, this would be a killer feature! |
How to wrap the original
This code is linked to the original TS code. And for each occurence of
the preprocessor would replace:
with
The code would look like this:
Note that the closure function So, for above example code, the preprocessor would generate:
and this would be now executed under standard typescript compiler, which would catch all errors. Anyway, I'm trying to find an easier way... |
For Handlebars:
it could work exactly the same way (just with more advanced data structures, but it all seems parsable):
in above example this:
has been replaced with:
Different templating engines...just the preprocessor would need a different analyser for underscore and handlebars syntax. AngularJS templates seem more complicated, though... Strict template propertiesHandlebars'
in above case, this would generate optional Above is handlebars's
that would determine, that a structure is a collection (just as Template base type: String and/or NumberAll above examples rely on strings. But numbers are valid atomic types of templating engines and should be supported by ts-based templates. And typescript compiler differentiates strings and numbers. Union types is a possible solution. Below code compiles with no errors:
Since JavaScript doesn't check types, the original underscore/handlebars/whatever template code doesn't contain information about the type. So, probably, we'd need to state |
i think the inlined templates are different from template files. i would say the inlined templates resolution can be solved by #3136. the standalone templates are different though. i do not think you want to infer types from them. you want to report errors there. e.g. <div class="entry">
<h1>{{lastname}}</h1>
</div> i want to get an error that I think this is more useful than saying that this template expects a type with one other thing to consider, is you want tooling as well. in your VSCode/VS/Sublime/Eclipse/Webstorm/etc... you want to hit "goto def" on That is why i was saying the template compiler generates .ts code, with type annotations, that is "linked" to the template code some how, and then the TS compiler/Langage Service understands it as part of your program. |
Regarding the <div class="entry">
<h1>{{lastname}}</h1>
</div> I'm not sure if you want to enforce developers to use CSS class property that way? At least I can see no other place where
I was thinking about generating .ts code as well, basing on template code, that would specify the types. I'm afraid I know too little about TS compiler internals. Let me know if I can help you further. |
Sorry my bad. I did not mean the css class, that was just a copy/past from your example. I meant whatever "contex" object this template will be bound to at runtime, the one expected to have a property lastName. |
Do you mean that, in order to suggest a solution, we need to divide all frontend templating engines into two groups:
|
I do not think I have a solution :) I was just brain storming. I do agree that there is a need for better experience here. If you would like to champion this issue and drive a proposal I would be willing to help. I think there is error reporting, either in the template as I mentioned or at the use side as you suggested; and the tooling support. |
@ducin @mhegazy I implemented my own solution: typed-tmpl. Let me know what you think! |
I've tried coming up with a solution for Angular 1.x templates based on JSX. Please have a look at my experiments. It looked really promising in the beginning, but unfortunately, even though the type-checking for JSX in TypeScript is really flexible, it turned out to be not flexible enough for Angular. See the first entry in the Issues section of README. If we have a look at an Angular component, we'll see that the attributes are bound directly to its properties, not to a separate
Yes, TypeScript started to understand that the attributes correspond to the properties of the component class. But then I discovered that the compiler wants to see all the class members as attributes, even methods, private properties, etc. If not all the members are represented as attributes, it generates an error. And there is no way to make the compiler require that only some properties be represented as attributes, not all. |
I am new to TypeScript and loved it.
I have installed package.json
tsconfig.json
also my webpack.config.js includes
I tried a lot but not able to figure out what is going wrong! my repository https://github.com/Protocore-UI/protocore-typescript-edition. Well, when I am excluding TypeScript and use ES6 with Webpack its working fine https://github.com/Protocore-UI/protocore-webpack-edition Is there any way to tell TypeScript to ignore my handlebars import, so that Webpack "handlebars-loader" can manage my handlebars templates. |
@hegdeashwin, the error is there because the compiler did not find a typescript file (.ts or .d.ts) to declare the shape of the module The simplest way is to say all // declarations.d.ts
declare module "*.handlebars" {
const _: string;
export default _;
} or just: // declarations.d.ts
declare module "*.handlebars"; // returns any see https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#wildcard-character-in-module-names for more details. |
Thank you @mhegazy that helped a lot, I added the declaration and gave the reference to declaration file in tsconfig.json file in files: [ "src/apps/templates/declarations.d.ts"] and the error is no more getting triggered but the HomeTemplate is undefined for both string and any type. Thus, my template is not getting rendered. I fixed the issue by just adding require declaration :
Removed "*.handlebars" module and its worked instead of undefined. |
I find interesting the approach taken by this framework.http://karaframework.com/docs/views.html It probably limits the usage in Html, but I would be much more confident of my templates with it. But that would be another template library, not using the ones we already have. |
I wrote a project to handle this issue specifically for angular1 views. It uses the typescript compiler API to parse the javascript and typescript code, htmlparser2 to parse the views, and the parsimmon parser combinator library to parse angular expressions (such as "for .. in .. track by .."). It then generates "viewtest" files, combining code from views and controllers, which then get type checked by the compiler at the same time as normal typescript files. It also allows the user to specify custom angular directives & filters to have them also type-checked. Obviously it does not support everything possible with angular1, by far, as the scope is huge, but we use it on a real-size project at work, and tested it on another real-size one too. You can find the project there: |
I've also written a tool with a similar aim to @emmanueltouzery's. However, it's a command line app, unlike |
That's is an interesting topic. HomeCtrl.js export default class HomeCtrl {
public myName:string = "Islam";
} HomeView.html <!-- vm as @HomeCtrl --> // That's the key
<div>
<span ng-bind="vm.myName"></span>
</div> Is the TypeScript team is willing to give this a priority? Because I know also an Angular 2+ teams that yet prefer to not inline the templates because of the "separation of concerns". So this problem is giving me and others to go with JSX where the most of us is still prefer the external templates files. Huge Thanks for your great work |
+1 on this feature. I would love to be able to type-check our pug templates. Even if we had to manually specify the "state" type manually through a comment in the template file, it would be a large improvement vs no type checking at all. |
The greatest feature of TypeScript, in terms of big enterprise apps, is type checking. When modifying/extending something low-level, I'll get all errors that arise beneath - just like I would in Java and .Net. But this relates to TS code.
My question is: is it possible to use TypeScript to check types used in frontend templating engines, such as Handlebars, Underscore or [your favourite templating engine]?
I've read that TypeScript 1.6 is gonna support react's JSX, but it's a big limitation to one specific engne only. I guess there is no built-in platform-supported solution, but maybe there is someone who made it work somehow?
Or, in other words, what would you do if you wanted to use TypeScript to check types of variables in handlebars/underscore templates?
The text was updated successfully, but these errors were encountered: