{"id":2348,"date":"2016-04-21T13:40:46","date_gmt":"2016-04-21T11:40:46","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=2348"},"modified":"2023-08-16T10:20:45","modified_gmt":"2023-08-16T08:20:45","slug":"creating-sharepoint-solutions-with-typescript","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/creating-sharepoint-solutions-with-typescript\/","title":{"rendered":"Creating SharePoint solutions with Typescript"},"content":{"rendered":"\n<p>This article will show you how to use typescript (<a href=\"http:\/\/www.typescriptlang.org\/\" rel=\"nofollow\" >http:\/\/www.typescriptlang.org\/<\/a> ) in your SharePoint solution in example of SharePoint-hosted app.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>We have a project, which has a requirement to create solution compatible with SharePoint-online as well as SharePoint on-premises. The challenging part was in the Deployment of the solution to SPWeb.<\/p>\n\n\n\n<p>To implement customer requirements we chose SharePoint-hosted app with possibility for auto-deployment of the whole infrastructure such as Content Types, Lists, Images, Webparts and scripts using JSOM API. Due to the fact that project contains few independent parts with the similar deployment requirements we decided to create a common reusable API. The best choice for this purpose was Typescript, which is strongly typed language with interfaces and extensible classes. The good point is the Typescript is compiled into Readable and Debuggable JavaScript code.<\/p>\n\n\n\n<p>The Typescripts files have .ts extensions and are compiled into .js and .map. The .map file has an exact line mapping of Typescript line of code in correlation to JavaScript line of code. This mapping information allows to debug Typescript using Visual Studio.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_1.png\"><img decoding=\"async\" width=\"284\" height=\"252\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_1.png\" alt=\"ts_1\" class=\"wp-image-2478\"\/><\/a><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The generated files are not added automatically into solution.<br>You need to configure Visual Studio in order to compile Typescript. Follow the steps below:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Install Typescript extension for Visual Studio from official site\n<ul class=\"wp-block-list\">\n<li><a href=\"http:\/\/www.typescriptlang.org\/\" rel=\"nofollow\" >http:\/\/www.typescriptlang.org\/<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Good news for developers \u2013 ReSharper support IntelliSense for Typescript. Please read details here\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/blog.jetbrains.com\/dotnet\/2014\/12\/15\/improved-typescript-support-in-resharper-9\/\" rel=\"nofollow\" >https:\/\/blog.jetbrains.com\/dotnet\/2014\/12\/15\/improved-typescript-support-in-resharper-9\/<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Create and configure Sharepoint-hosted app project in Visual Studio:\n<ul class=\"wp-block-list\">\n<li>Create SharePoint-hosted app<\/li>\n\n\n\n<li>Add NuGet package to a project: Microsoft.TypeScript.MSBuild<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Add NuGets with Typescript definitions. The key word for Typescript definitions is \u201cdefinitelytyped\u201d, for example, the search result for sharepoint definitelytyped is:<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_2.png\"><img decoding=\"async\" width=\"300\" height=\"46\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_2-300x46.png\" alt=\"ts_2\" class=\"wp-image-2480\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_2-300x46.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_2-1024x156.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_2.png 1200w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/figure>\n\n\n\n<p><br>The same way you can find jquery definitelytyped Typescript definition. The result of the nuget installation is folder with \u201ctypings\u201d name which contains package subfolder with an *.d.ts extension file.<br><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_3.png\"><img decoding=\"async\" width=\"251\" height=\"112\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_3.png\" alt=\"ts_3\" class=\"wp-image-2481\"\/><\/a><\/figure>\n\n\n\n<p>After this configuration, Visual Studio would be able to compile typescripts and it will add new<br>\u201cTypescript\u201d tab to project properties.<br>Let\u2019s create simple project using Typescript to provision Content Types to Site Collection. We need four files to do it (the same as in C# good solution is to separate classes and responsibilities per file):<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>ProvisionDefinition.ts \u2013 the static module which defines provisioning rules (contentype names, list names, fields, file locations).<\/li>\n\n\n\n<li>ContentTypeModel.ts \u2013 object with the list of properties defining conten type<\/li>\n\n\n\n<li>DeploymentTool.ts \u2013 the \u201cservice\u201d wrapping the sharepoint API<\/li>\n\n\n\n<li>Main.ts \u2013 the main module represents the interface for UI<\/li>\n<\/ol>\n\n\n\n<p>After the adding of files and rebuilding of the project click the \u201cShow all files\u201d button in solution window of Visual Studio:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_4.png\"><img decoding=\"async\" width=\"176\" height=\"89\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_4.png\" alt=\"ts_4\" class=\"wp-image-2482\"\/><\/a><\/figure>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>As a result, you will see the list of compiled files next to created .ts files. Please add all the .js files into solution.<br>The next step is to define content types and its properties. Below you could find the content type definition TS file and its compiled JS:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_5.png\"><img decoding=\"async\" width=\"300\" height=\"105\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_5-300x105.png\" alt=\"ts_5\" class=\"wp-image-2483\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_5-300x105.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_5-1024x358.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_5.png 1417w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/figure>\n\n\n\n<p>The definition of Missing ContentTypeModel class is very simple: just a constructor and the list of simple properties:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nclass ContentTypeModel {\nconstructor(options) {\nthis.Name = options.Name;\nthis.Group = options.Group;\nthis.Description = options.Description;\nthis.Inherits = options.Inherits;\nthis.Version = options.Version;\nthis.ParentName = options.ParentName;\n}\n \npublic Name: string;\npublic Group: string;\npublic Description: string;\npublic Inherits: string;\npublic Version: string;\npublic ParentName: string;\n}\n<\/pre><\/div>\n\n\n<p>The definition of Service class <strong>DeploymentTool <\/strong>has a strong type constructor and a couple of methods:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nclass DeploymentTool {\nprivate web: SP.Web;\nprivate clientContext: SP.ClientContext;\n \nconstructor(clientContext: SP.ClientContext, web: SP.Web) {\nthis.web = web;\nthis.clientContext = clientContext;\n}\n \npublic createContentTypes(contentTypesDefinitions: Array&lt;ContentTypeModel&gt;, done: any ): void {\ntry {\nfor (var i = 0; i &lt; contentTypesDefinitions.length; i++) { this.createContentType(contentTypesDefinitions&amp;#91;i&amp;#93;, (contentType: SP.ContentType, error: string) =&gt; {\nif(contentType != null)\n{ console.log(&quot;Content type with name: &quot; + contentType.get_name() + &quot; and ID: &quot; + contentType.get_stringId() + &quot; has been created&quot;); }\nif (error != null) {\nconsole.log(error);\n}\n});\n}\n} catch (ex) {\ndone(ex);\n}\ndone(null);\n}\n \nprivate getContentTypeByName(contentTypeCol, ctName) {\nvar myCt = null;\nvar contentTypeEnumerator = contentTypeCol.getEnumerator();\nwhile (contentTypeEnumerator.moveNext()) {\nvar content = contentTypeEnumerator.get_current();\nif (content.get_name() === ctName) {\nmyCt = content;\nbreak;\n}\n}\nreturn myCt;\n}\n \nprivate createContentType(contentTypesDefinition: ContentTypeModel, done: any): void {\nvar webContentTypes = this.web.get_contentTypes();\nvar these = this;\nthese.clientContext.load(webContentTypes);\nthese.clientContext.executeQueryAsync(() =&gt; {\nvar current = these.getContentTypeByName(webContentTypes, contentTypesDefinition.Name);\nif (current != null) {\ndone(current);\nreturn;\n}\nvar newContentType = new SP.ContentTypeCreationInformation();\nnewContentType.set_name( contentTypesDefinition.Name);\nnewContentType.set_description( contentTypesDefinition.Description);\nnewContentType.set_group( contentTypesDefinition.Group);\nvar parent = these.getContentTypeByName( webContentTypes, contentTypesDefinition.ParentName);\nnewContentType.set_parentContentType(parent);\ncurrent = webContentTypes.add(newContentType);\nthese.clientContext.load(current);\nthese.clientContext.load(webContentTypes);\nthese.clientContext.executeQueryAsync(() =&gt; {\ndone(current, null);\n}, (sender, args) =&gt; {\ndone(null, args.get_message());\n});\n}, () =&gt; {\nconsole.log(contentTypesDefinition.Name + &quot; provision error&quot;);\n});\n}\n}\n<\/pre><\/div>\n\n\n<p>The signature of the most important method here is createContentType(contentTypesDefinition: ContentTypeModel, done: any): void and it means that we have first parameter strongly typed ContentTypeModel and the second one delegate to post back event called done. The method itself returns void. Luckily included sharepoint.d.ts definition file contains all the SP.ContentTypeCreationInformation object methods and intellisence help us to define new ContenType:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_6.png\"><img decoding=\"async\" width=\"300\" height=\"107\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_6-300x107.png\" alt=\"ts_6\" class=\"wp-image-2484\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_6-300x107.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/03\/ts_6.png 824w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/figure>\n\n\n\n<p>And the couple of last steps to create simple UI and newly created API interaction. Add JS links into default.aspx page<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;script type=&quot;text\/javascript&quot; src=&quot;..\/Scripts\/jquery-1.9.1.min.js&quot;&gt;&lt;\/script&gt;\n&lt;script type=&quot;text\/javascript&quot; src=&quot;..\/Scripts\/AppScripts\/ContentTypeModel.js&quot;&gt;&lt;\/script&gt;\n&lt;script type=&quot;text\/javascript&quot; src=&quot;..\/Scripts\/AppScripts\/DeploymentTool.js&quot;&gt;&lt;\/script&gt;\n&lt;script type=&quot;text\/javascript&quot; src=&quot;..\/Scripts\/AppScripts\/ProvisionDefinition.js&quot;&gt;&lt;\/script&gt;\n&lt;script type=&quot;text\/javascript&quot; src=&quot;..\/Scripts\/AppScripts\/Main.js&quot;&gt;&lt;\/script&gt;\n<\/pre><\/div>\n\n\n<p>Define the button to start deployment:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;div&gt;\n&lt;input type=&quot;button&quot; value=&quot;Provision content types&quot; class=&quot;main-btn&quot; style=&quot;display: none&quot; id=&quot;provisionContentTypes&quot; onclick=&quot;UiFunctions.ButtonClicks.contentTypeProvision()&quot;\/&gt;\n&lt;\/div&gt;\n<\/pre><\/div>\n\n\n<p>And the main.ts file will contain \u201condocumentready\u201d event with loading of all required sharepoint scripts and module definition for event functions:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nvar _deploymentTool;\n$(document).ready(() =&gt; {\nvar scriptbase = _spPageContextInfo.layoutsUrl + &quot;\/&quot;;\n$.getScript(scriptbase + &quot;SP.Runtime.js&quot;, () =&gt; {\n$.getScript(scriptbase + &quot;SP.js&quot;, () =&gt; {\nvar context = new SP.ClientContext(_spPageContextInfo.siteServerRelativeUrl);\nvar web = context.get_web();\ncontext.load(web);\ncontext.executeQueryAsync(() =&gt; {\n_deploymentTool = new DeploymentTool(context, web);\n$(&quot;#provisionContentTypes&quot;).show();\n}, () =&gt; {\nconsole.log(&quot;SP.Web initialization failed&quot;);\n});\n});\n});\n});\n \nmodule UiFunctions {\nexport module ButtonClicks {\nexport function contentTypeProvision() {\n \n_deploymentTool.createContentTypes( Deployment.ContentTypes, () =&gt; {\nconsole.log(&quot;content type provisioning&quot;);\n});\n}\n}\n}\n<\/pre><\/div>\n\n\n<p>The difference between module and class is that the module can play the same role as a C# static context.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>So, the summary is simple \u2013 typescript allows to create client side code with normal object oriented structure, plus we finally have a possibility to see the intellisence for SharePoint, angular, knockout, jQuery and other APIs. Thanks to all people who worked on it.<br>Useful links:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"http:\/\/www.typescriptlang.org\/\" rel=\"nofollow\" >http:\/\/www.typescriptlang.org\/<\/a> &#8211; Typescript homepage<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/gandjustas\/sptypescript\" rel=\"nofollow\" >https:\/\/github.com\/gandjustas\/sptypescript<\/a> &#8211; SharePoint typescript homepage<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/DefinitelyTyped\/DefinitelyTyped\" rel=\"nofollow\" >https:\/\/github.com\/DefinitelyTyped\/DefinitelyTyped<\/a> a LOT of definitely typed libraries<\/li>\n<\/ol>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;2348&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 ( votes: 0)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Creating SharePoint solutions with Typescript&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>This article will show you how to use typescript (http:\/\/www.typescriptlang.org\/ ) in your SharePoint solution in example of SharePoint-hosted app. &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/creating-sharepoint-solutions-with-typescript\/\">Continued<\/a><\/p>\n","protected":false},"author":81,"featured_media":537,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1320],"tags":[1345,1338,1482,1474],"class_list":["post-2348","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-sharepoint-en","tag-javascript-en","tag-solutions-en","tag-typescript-en"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2015\/10\/16_SharePoint_v2.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/2348"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/81"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=2348"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/2348\/revisions"}],"predecessor-version":[{"id":23488,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/2348\/revisions\/23488"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/537"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=2348"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=2348"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=2348"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}