{"id":202,"date":"2018-02-12T13:03:48","date_gmt":"2018-02-12T11:03:48","guid":{"rendered":"http:\/\/carsten.familie-schumann.info\/blog\/?page_id=202"},"modified":"2018-02-12T15:42:49","modified_gmt":"2018-02-12T13:42:49","slug":"fallstricke-bei-typescript","status":"publish","type":"page","link":"https:\/\/carsten.familie-schumann.info\/blog\/fallstricke-bei-typescript\/","title":{"rendered":"Fallstricke bei TypeScript"},"content":{"rendered":"<p>Typescript ist toll&#8230;.vor allem wenn man von Java, C#, C++ oder einer anderen streng typisierten Sprache kommt. Es h\u00e4lt aber auch ein paar mehr oder weniger b\u00f6se Fallstricke bereit. Diese Seite zeigt eine kleine Liste von <em>bekannten Effekten<\/em>, die man kennen sollte.<\/p>\n<h1>Webpack und Watch<\/h1>\n<p>Webpack bietet die M\u00f6glichkeit, mit dem Parameter <code>--watch<\/code> oder <code>-w<\/code> seine Quellcodedateien \u00fcberwachen zu lassen. Sobald sich eine \u00c4nderung ergibt, wird das Projekt (inkrementell) aktualisiert. Das ist besonders praktisch, wenn man Fehler im Code sucht und immer nur kleine \u00c4nderungen machen m\u00f6chte. Dabei beh\u00e4lt Webpack auch die ganzen Abh\u00e4ngigkeiten im Blick und aktualisiert das Projekt auch bei einer ver\u00e4nderten Abh\u00e4ngigkeit. Alle Abh\u00e4ngigkeiten? NEEEIN.<\/p>\n<p>Von der Abh\u00e4ngigkeitsbetrachtung werden <code>*.d.ts<\/code>-Dateien ausgenommen. Diese enthalten Definitionen, wie normales JavaScript aussieht und bietet die M\u00f6glichkeit, auch die Schnittstelle zum JavaScript einer statischen Codeanalyse zu unterziehen. Wenn man jedoch diese Dateien \u00e4ndert, muss man den Webpack-Prozess neu starten!<\/p>\n<p>Merke: <strong>Die Webpack-Option <code>--watch<\/code> oder <code>-w<\/code> schlie\u00dft <code>*.d.ts<\/code>-Dateien nicht mit ein, sondern nur, was \u00fcber <em>import<\/em> eingebunden wurde!<\/strong><\/p>\n<h1>Import, ReferenceTypes oder ReferencePath<\/h1>\n<p>TypeScript bietet mehrere M\u00f6glichkeiten, Abh\u00e4ngigkeiten zu definieren. Diese sind (am Beispiel der Datei snapsvg):<\/p>\n<pre class=\"brush: typescript; title: ; notranslate\" title=\"\">\r\n\/\/ 1: Lokale Deklaration\r\n\/\/\/ &lt;reference path='..\/node_modules\/@types\/snapsvg\/index.d.ts' \/&gt;\r\n\r\n\/\/ 2: Benannter Typ\r\n\/\/\/ &lt;reference types=&quot;snapsvg&quot; \/&gt;\r\n\r\n\/\/ 3. ts Datei (eigentlich)\r\nimport * as Snap from 'snapsvg';\r\n<\/pre>\n<p>Die ersten beiden sind f\u00fcr den Import von <code>*.d.ts<\/code>-Dateien gedacht. Die Deklarationen m\u00fcssen am Anfang einer <code>.ts<\/code>-Datei stehen (vor Code) und <strong>wirken sich auf das gesamte Projekt aus<\/strong>! Es ist also vollkommen egal, wo sie stehen, sie gelten immer. Das kann zu Verwirrungen f\u00fchren. Fall 1 sollte man normalerweise f\u00fcr lokal liegende Definitionsdateien verwenden, wo man einen relativen Pfad kennt, Fall 2 hingegen f\u00fcr Sachen aus <em>DefinitelyTyped<\/em> die unter <em>node_modules\/@types\/&#8230;.<\/em> liegen. \u00dcbrigens: Auch wenn es <em>reference types<\/em> hei\u00dft, kann man immer nur einen Typen importieren. Bei mehreren Typen muss man halt mehrere Zeilen schreiben.<\/p>\n<p>In der <em>tsconfig.json<\/em> sollte sich folgender Eintrag finden, der angibt, wo reference types gesucht werden:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n{\r\n    &quot;compilerOptions&quot;: {\r\n        \/\/ &#x5B;...]\r\n        &quot;typeRoots&quot;: &#x5B;\r\n            \/\/ add path to @types\r\n            &quot;node_modules\/@types&quot;\r\n        ], \r\n        \/\/ &#x5B;...]\r\n   }\r\n}\r\n<\/pre>\n<p>Die letzte Deklaration ist schlie\u00dflich ein tats\u00e4chlicher Import von Code, der typischerweise komplett in TypeScript geschrieben ist. Sofern man auf die Idee kommt, diesen Import auch f\u00fcr  <code>*.d.ts<\/code>-Dateien zu verwenden, endet dies in komischen Fehlermeldunge, sobald man Dinge \u00fcberladen m\u00f6chte oder an anderer Stelle <em>Declaration Merging<\/em> verwenden will.<\/p>\n<p>Merke:<\/p>\n<ol>\n<li><strong><em>reference types<\/em> nur f\u00fcr <em>@types<\/em><\/strong><\/li>\n<li><strong><em>reference path<\/em> nur f\u00fcr lokale .d.ts Dateien<\/strong><\/li>\n<li><strong><em>import <\/em>nur f\u00fcr richtiges TypeScript (.ts)<\/strong><\/li>\n<li><strong><em>reference types<\/em> und <em>reference path<\/em> wirkt sich auf alle .ts Dateien aus!<\/strong><\/li>\n<\/ol>\n<h1>Declaration Merging<\/h1>\n<p>Declaration Merging ist cool. Speziell dann, wenn man Bibliotheken durch das Hinzuf\u00fcgen von Funktionen erweitert und diese Funktionen sp\u00e4ter noch im TypeScript nutzen m\u00f6chte. In diesem Fall muss man n\u00e4mlich nicht die urspr\u00fcngliche <code>*.d.ts<\/code>-Datei erweitern sondern erg\u00e4nzt sie sozusagen. Dazu m\u00fcssen jedoch ein paar Vorraussetzungen in den Definitionsdateien erf\u00fcllt sein.<\/p>\n<ol>\n<li>Namespaces und Funktionen mit gleichem Namen f\u00fchren zu Problemen.<\/li>\n<li>Klassen und Namespaces mit gleichem Namen klappen. (warum auch immer)<\/li>\n<li>Es werden nur Definitionsdateien zusammengef\u00fchrt. Eine <code>.d.ts<\/code>-Datei mit einer <code>*.ts<\/code>-Datei zu erweitern geht nicht.<\/li>\n<\/ol>\n<p>Hier ein Beispiel, wo Snapsvg um eine zus\u00e4tzliche Methode erweitert wird. Die Methode ist in JavaScript als Plugin f\u00fcr Snap geschrieben, aber irgendwie muss man das ja nach TypeScript bekommen. <em>@types\/snapsvg\/index.d.ts<\/em> (Auszug):<\/p>\n<pre class=\"brush: typescript; title: ; notranslate\" title=\"\">\r\ndeclare module &quot;snapsvg&quot; {\r\n    export = Snap;\r\n}\r\n\r\ndeclare const Snap: SnapStatic;\r\ninterface SnapStatic {\r\n    filter:Filter;   \r\n    path:Path;\r\n\r\n    (width:number|string,height:number|string):Snap.Paper;\r\n    (query:string):Snap.Paper;\r\n    (DOM:SVGElement):Snap.Paper;\r\n    \/\/ &#x5B;...]\r\n}\r\n\r\ndeclare namespace Snap{\r\n    interface Paper extends Snap.Element {\r\n        \/\/ &#x5B;...]\r\n    }\r\n}\r\n<\/pre>\n<p><em>.\/snap-extensions.d.ts<\/em>:<\/p>\n<pre class=\"brush: typescript; title: ; notranslate\" title=\"\">\r\nnamespace Snap {\r\n    export interface Paper{\r\n        translate(dx:Number, dy:Number):Snap.Paper;\r\n    }\r\n}\r\n<\/pre>\n<p>Zuletzt noch die Zusammenf\u00fchrung der Module:<\/p>\n<pre class=\"brush: typescript; title: ; notranslate\" title=\"\">\r\n\/\/\/ &lt;reference types=&quot;snapsvg&quot; \/&gt;\r\n\/\/\/ &lt;reference path=&quot;.\/snap-extensions.d.ts&quot; \/&gt;\r\n\r\nclass SvgGraph{\r\n    constructor(container: JQuery)\r\n    {\r\n        let paper: Snap.Paper = Snap(container);\r\n        paper.circle(10,20,4);\r\n        paper.translate(4,2);\r\n    }\r\n    \/\/ &#x5B;...]\r\n}\r\n<\/pre>\n<p>Merke:<\/p>\n<ol>\n<li><strong>Declaration Merging funktioniert nur in <code>.d.ts<\/code>-Dateien.<\/strong><\/li>\n<li><strong>Declaration Merging funktioniert nur, wenn es keine Namespace-Funktion-Kollision gibt.<\/strong><\/li>\n<li><strong>Declaration Merging funktioniert nur, wenn die <code>.d.ts<\/code>-Dateien per <em>reference<\/em> importiert wurden.<\/strong><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Typescript ist toll&#8230;.vor allem wenn man von Java, C#, C++ oder einer anderen streng typisierten Sprache kommt. Es h\u00e4lt aber auch ein paar mehr oder weniger b\u00f6se Fallstricke bereit. Diese Seite zeigt eine kleine Liste von bekannten Effekten, die man kennen sollte. Webpack und Watch Webpack bietet die M\u00f6glichkeit, mit dem Parameter &#8211;watch oder -w&#8230;<br \/><a class=\"read-more-button\" href=\"https:\/\/carsten.familie-schumann.info\/blog\/fallstricke-bei-typescript\/\">Mehr Lesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-202","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/pages\/202","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/comments?post=202"}],"version-history":[{"count":12,"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/pages\/202\/revisions"}],"predecessor-version":[{"id":205,"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/pages\/202\/revisions\/205"}],"wp:attachment":[{"href":"https:\/\/carsten.familie-schumann.info\/blog\/wp-json\/wp\/v2\/media?parent=202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}