1 element modules
2 tag
3 ast
4 category
5 item
6 title Exporting a declaration
7 expected
8 + /* Validation.ts */
9 + export interface StringValidator {
10 + isAcceptable(s: string): boolean;
11 + }
12 + /* ZipCodeValidator.ts */
13 + export const numberRegexp = /^[0-9]+$/;
14 + export class ZipCodeValidator implements StringValidator {
15 + isAcceptable(s: string) {
16 + return s.length === 5 && numberRegexp.test(s);
17 + }
18 + }
19 ittf
20 +
21 #
22 # Validation.ts
23 export
24 :interface StringValidator
25 :m isAcceptable
26 :boolean
27 param s
28 :string
29 #
30 # ZipCodeValidator.ts
31 export
32 const numberRegexp = /^[0-9]+$/
33 export
34 class ZipCodeValidator
35 :implements StringValidator
36 m isAcceptable
37 param s
38 :string
39 return s.length === 5 && numberRegexp.test(s)
40 item
41 title Export statements
42 expected
43 + class ZipCodeValidator implements StringValidator {
44 + isAcceptable(s: string) {
45 + return s.length === 5 && numberRegexp.test(s);
46 + }
47 + }
48 + export { ZipCodeValidator };
49 + export { ZipCodeValidator as mainValidator };
50 ittf
51 +
52 class ZipCodeValidator
53 :implements StringValidator
54 m isAcceptable
55 param s
56 :string
57 return s.length === 5 && numberRegexp.test(s)
58 export
59 @ ZipCodeValidator
60 export
61 @ ZipCodeValidator
62 as mainValidator
63 item
64 title Re - exports
65 expected
66 + /* ParseIntBasedZipCodeValidator.ts */
67 + export class ParseIntBasedZipCodeValidator {
68 + isAcceptable(s: string) {
69 + return s.length === 5 && parseInt(s).toString() === s;
70 + }
71 + }
72 + // Export original validator but rename it
73 + export { ZipCodeValidator as RegExpBasedZipCodeValidator } from "./ZipCodeValidator";
74 + // Optionally, a module can wrap one or more modules and combine all their exports using export * from "module" syntax.
75 + /* AllValidators.ts */
76 + export * from "./StringValidator"; // exports interface 'StringValidator'
77 + export * from "./LettersOnlyValidator"; // exports class 'LettersOnlyValidator'
78 + export * from "./ZipCodeValidator"; // exports class 'ZipCodeValidator'
79 ittf
80 +
81 #
82 # ParseIntBasedZipCodeValidator.ts
83 export
84 class ParseIntBasedZipCodeValidator
85 m isAcceptable
86 param s
87 :string
88 return s.length === 5 && parseInt(s).toString() === s
89 export
90 @ ZipCodeValidator
91 as RegExpBasedZipCodeValidator
92 from "./ZipCodeValidator"
93 #
94 # AllValidators.ts
95 export *
96 from "./StringValidator"
97 export *
98 from "./LettersOnlyValidator"
99 export *
100 from "./ZipCodeValidator"
101 item
102 title Import a single export from a module
103 expected
104 + import { ZipCodeValidator } from "./ZipCodeValidator";
105 + let myValidator = new ZipCodeValidator();
106 + /* imports can also be renamed */
107 + import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
108 + let myValidator = new ZCV();
109 + /* Import the entire module into a single variable, and use it to access the module exports */
110 + import * as validator from "./ZipCodeValidator";
111 + let myValidator = new validator.ZipCodeValidator();
112 + /* Import a module for side- effects only */
113 + import "./my-module.js";
114 ittf
115 +
116 import
117 @ ZipCodeValidator
118 from "./ZipCodeValidator"
119 let myValidator = new ZipCodeValidator()
120 #
121 # imports can also be renamed
122 import
123 @ ZipCodeValidator
124 as ZCV
125 from "./ZipCodeValidator"
126 let myValidator = new ZCV()
127 #
128 # Import the entire module into a single variable, and use it to access the module exports
129 import
130 as validator
131 from "./ZipCodeValidator"
132 let myValidator = new validator.ZipCodeValidator()
133 #
134 # Import a module for side- effects only
135 import "./my-module.js"
136 item
137 title Default exports
138 expected
139 + /* JQuery.d.ts */
140 + declare let $: JQuery;
141 + export default $;
142 + /* App.ts */
143 + import $ from "JQuery";
144 + $("button.continue").html("Next Step...");
145 ittf
146 +
147 #
148 # JQuery.d.ts
149 :declare
150 let
151 :ref JQuery
152 export-default
153 #
154 # App.ts
155 import $ from "JQuery"
156 _ $("button.continue").html("Next Step...")
157 item
158 title Default exports of classes and functions
159 expected
160 + /* ZipCodeValidator.ts */
161 + export default class ZipCodeValidator {
162 + static numberRegexp = /^[0-9]+$/;
163 + isAcceptable(s: string) {
164 + return s.length === 5 && ZipCodeValidator.numberRegexp.test(s);
165 + }
166 + }
167 + /* Test.ts */
168 + import validator from "./ZipCodeValidator";
169 + let myValidator = new validator();
170 + /* or StaticZipCodeValidator.ts */
171 + const numberRegexp = /^[0-9]+$/;
172 + export default function (s: string) {
173 + return s.length === 5 && numberRegexp.test(s);
174 + }
175 + /* Test.ts */
176 + import validate from "./StaticZipCodeValidator";
177 + let strings = ["Hello", "98052", "101"];
178 + // Use function validate
179 + strings.forEach(s => {
180 + console.log(`"${s}" ${validate(s) ? " matches" : " does not match"}`);
181 + });
182 ittf
183 +
184 #
185 # ZipCodeValidator.ts
186 export-default
187 class ZipCodeValidator
188 p numberRegexp
189 static
190 := /^[0-9]+$/
191 m isAcceptable
192 param s
193 :string
194 return s.length === 5 && ZipCodeValidator.numberRegexp.test(s)
195 #
196 # Test.ts
197 import validator from "./ZipCodeValidator"
198 let myValidator = new validator()
199 #
200 # or
201 # StaticZipCodeValidator.ts
202 const numberRegexp = /^[0-9]+$/
203 export-default
204 function
205 param s
206 :string
207 return s.length === 5 && numberRegexp.test(s)
208 #
209 # Test.ts
210 import validate from "./StaticZipCodeValidator"
211 let strings
212 [
213 @ "Hello"
214 @ "98052"
215 @ "101"
216 _ strings.forEach
217 =>
218 param s
219 _ console.log
220 template
221 + "
222 @ s
223 + "${}
224 iif validate(s)
225 then " matches"
226 else " does not match"
227 +
228 item
229 title Default exports can also be just values:
230 expected
231 + /* default exports can also be just values: */
232 + /* OneTwoThree.ts */
233 + export default "123";
234 + /* Log.ts */
235 + import num from "./OneTwoThree";
236 + console.log(num); // "123"
237 ittf
238 +
239 #
240 # OneTwoThree.ts
241 export-default "123"
242 #
243 # Log.ts
244 import num from "./OneTwoThree"
245 _ console.log(num)
246 item
247 title export = and import = require()
248 expected
249 + /* ZipCodeValidator.ts */
250 + let numberRegexp = /^[0-9]+$/;
251 + class ZipCodeValidator {
252 + isAcceptable(s: string) {
253 + return s.length === 5 && numberRegexp.test(s);
254 + }
255 + }
256 + export = ZipCodeValidator;
257 + /* Test.ts */
258 + import zip = require("./ZipCodeValidator");
259 + // Some samples to try
260 + let strings = ["Hello", "98052", "101"];
261 + // Validators to use
262 + let validator = new zip();
263 + // Show whether each string passed each validator
264 + strings.forEach(s => {
265 + console.log(`"${s}" - ${validator.isAcceptable(s) ? "matches" : "does not match"}`);
266 + });
267 ittf
268 +
269 #
270 # ZipCodeValidator.ts
271 let numberRegexp = /^[0-9]+$/
272 class ZipCodeValidator
273 m isAcceptable
274 param s
275 :string
276 return s.length === 5 && numberRegexp.test(s)
277 :export ZipCodeValidator
278 #
279 # Test.ts
280 :import zip
281 :require "./ZipCodeValidator"
282 let strings
283 [
284 @ "Hello"
285 @ "98052"
286 @ "101"
287 let validator = new zip()
288 _ strings.forEach
289 =>
290 param s
291 _ console.log
292 template
293 + "
294 @ s
295 + " -${}
296 iif validator.isAcceptable(s)
297 then "matches"
298 else "does not match"
299 +
300 item
301 title Code Generation for Modules
302 expected
303 + import m = require("mod");
304 + export let t = m.something + 1;
305 + /* AMD / RequireJS SimpleModule.js */
306 + define(["require", "exports", "./mod"], function (require, exports, mod_1) {
307 + exports.t = mod_1.something + 1;
308 + });
309 + /* CommonJS / Node SimpleModule.js */
310 + var mod_1 = require("./mod");
311 + exports.t = mod_1.something + 1;
312 + /* UMD SimpleModule.js */
313 + (function (factory) {
314 + if (typeof module === "object" && typeof module.exports === "object") {
315 + var v = factory(require, exports); if (v !== undefined) module.exports = v;
316 + } else if (typeof define === "function" && define.amd) {
317 + define(["require", "exports", "./mod"], factory);
318 + }
319 + })(function (require, exports) {
320 + var mod_1 = require("./mod");
321 + exports.t = mod_1.something + 1;
322 + });
323 + /* System SimpleModule.js */
324 + System.register(["./mod"], function (exports_1) {
325 + var mod_1;
326 + var t;
327 + return {
328 + setters: [
329 + function (mod_1_1) {
330 + mod_1 = mod_1_1;
331 + }],
332 + execute: function () {
333 + exports_1("t", t = mod_1.something + 1);
334 + }
335 + }
336 + });
337 + /* Native ECMAScript 2015 modules SimpleModule.js */
338 + import { something } from "./mod";
339 + export var t = something + 1;
340 ittf
341 +
342 :import m
343 :require "mod"
344 export
345 let t = m.something + 1
346 #
347 # AMD / RequireJS SimpleModule.js
348 _ define
349 [
350 @ "require"
351 @ "exports"
352 @ "./mod"
353 function
354 param require
355 param exports
356 param mod_1
357 set exports.t = mod_1.something + 1
358 #
359 # CommonJS / Node SimpleModule.js
360 var mod_1 = require("./mod")
361 set exports.t = mod_1.something + 1
362 #
363 # UMD SimpleModule.js
364 iife
365 param factory
366 if typeof module === "object" && typeof module.exports === "object"
367 var v = factory(require, exports)
368 if v !== undefined
369 set module.exports = v
370 else
371 if typeof define === "function" && define.amd
372 _ define
373 [
374 @ "require"
375 @ "exports"
376 @ "./mod"
377 @ factory
378 ()
379 function
380 param require
381 param exports
382 var mod_1 = require("./mod")
383 set exports.t = mod_1.something + 1
384 #
385 # System SimpleModule.js
386 _ System.register
387 [
388 @ "./mod"
389 function
390 param exports_1
391 var mod_1
392 var t
393 return
394 {
395 [ setters
396 function
397 param mod_1_1
398 set mod_1 = mod_1_1
399 @ execute
400 function
401 _ exports_1
402 @ "t"
403 set t = mod_1.something + 1
404 #
405 # Native ECMAScript 2015 modules SimpleModule.js
406 import
407 @ something
408 from "./mod"
409 export
410 var t = something + 1
411 item
412 title Simple Example
413 expected
414 + /* Validation.ts */
415 + export interface StringValidator {
416 + isAcceptable(s: string): boolean;
417 + }
418 + /* LettersOnlyValidator.ts */
419 + import { StringValidator } from "./Validation";
420 + const lettersRegexp = /^[A-Za-z]+$/;
421 + export class LettersOnlyValidator implements StringValidator {
422 + isAcceptable(s: string) {
423 + return lettersRegexp.test(s);
424 + }
425 + }
426 + /* ZipCodeValidator.ts */
427 + import { StringValidator } from "./Validation";
428 + const numberRegexp = /^[0-9]+$/;
429 + export class ZipCodeValidator implements StringValidator {
430 + isAcceptable(s: string) {
431 + return s.length === 5 && numberRegexp.test(s);
432 + }
433 + }
434 + /* Test.ts */
435 + import { StringValidator } from "./Validation";
436 + import { ZipCodeValidator } from "./ZipCodeValidator";
437 + import { LettersOnlyValidator } from "./LettersOnlyValidator";
438 + // Some samples to try
439 + let strings = ["Hello", "98052", "101"];
440 + // Validators to use
441 + let validators: { [s: string]: StringValidator; } = {};
442 + validators["ZIP code"] = new ZipCodeValidator();
443 + validators["Letters only"] = new LettersOnlyValidator();
444 + // Show whether each string passed each validator
445 + strings.forEach(s => {
446 + for (let name in validators) {
447 + console.log(`"${s}" - ${validators[name].isAcceptable(s) ? "matches" : "does not match"} ${name}`);
448 + }
449 + });
450 ittf
451 +
452 #
453 # Validation.ts
454 export
455 :interface StringValidator
456 :m isAcceptable
457 :boolean
458 param s
459 :string
460 #
461 # LettersOnlyValidator.ts
462 import
463 @ StringValidator
464 from "./Validation"
465 const lettersRegexp = /^[A-Za-z]+$/
466 export
467 class LettersOnlyValidator
468 :implements StringValidator
469 m isAcceptable
470 param s
471 :string
472 return lettersRegexp.test(s)
473 #
474 # ZipCodeValidator.ts
475 import
476 @ StringValidator
477 from "./Validation"
478 const numberRegexp = /^[0-9]+$/
479 export
480 class ZipCodeValidator
481 :implements StringValidator
482 m isAcceptable
483 param s
484 :string
485 return s.length === 5 && numberRegexp.test(s)
486 #
487 # Test.ts
488 import
489 @ StringValidator
490 from "./Validation"
491 import
492 @ ZipCodeValidator
493 from "./ZipCodeValidator"
494 import
495 @ LettersOnlyValidator
496 from "./LettersOnlyValidator"
497 let strings
498 [
499 @ "Hello"
500 @ "98052"
501 @ "101"
502 let validators
503 :{
504 :index
505 :ref StringValidator
506 param s
507 :string
508 {
509 set validators["ZIP code"] = new ZipCodeValidator()
510 set validators["Letters only"] = new LettersOnlyValidator()
511 _ strings.forEach
512 =>
513 param s
514 for let name in validators
515 _ console.log
516 template
517 + "
518 @ s
519 + " -${}
520 iif validators[name].isAcceptable(s)
521 then "matches"
522 else "does not match"
523 + ${}
524 @ name
525 +
526 item
527 title Optional Module Loading
528 expected
529 + /* Dynamic Module Loading in Node.js */
530 + declare function require(moduleName: string): any;
531 + import { ZipCodeValidator as Zip } from "./ZipCodeValidator";
532 + if (needZipValidation) {
533 + let ZipCodeValidator: typeof Zip = require("./ZipCodeValidator");
534 + let validator = new ZipCodeValidator();
535 + if (validator.isAcceptable("...")) { /* ... */ }
536 + }
537 + /* Sample: Dynamic Module Loading in require.js */
538 + declare function require(moduleNames: string[], onLoad: (...args: any[]) => void): void;
539 + import * as Zip from "./ZipCodeValidator";
540 + if (needZipValidation) {
541 + require(["./ZipCodeValidator"], (ZipCodeValidator: typeof Zip) => {
542 + let validator = new ZipCodeValidator.ZipCodeValidator();
543 + if (validator.isAcceptable("...")) { /* ... */ }
544 + });
545 + }
546 + /* Sample: Dynamic Module Loading in System.js */
547 + declare const System: any;
548 + import { ZipCodeValidator as Zip } from "./ZipCodeValidator";
549 + if (needZipValidation) {
550 + System.import("./ZipCodeValidator").then((ZipCodeValidator: typeof Zip) => {
551 + var x = new ZipCodeValidator();
552 + if (x.isAcceptable("...")) { /* ... */ }
553 + });
554 + }
555 ittf
556 +
557 #
558 # Dynamic Module Loading in Node.js
559 :declare
560 :function require
561 param moduleName
562 :string
563 :return
564 :any
565 import
566 @ ZipCodeValidator
567 as Zip
568 from "./ZipCodeValidator"
569 if needZipValidation
570 let ZipCodeValidator
571 :typeof Zip
572 _ require("./ZipCodeValidator")
573 let validator = new ZipCodeValidator()
574 if validator.isAcceptable("...")
575 #
576 # Sample: Dynamic Module Loading in require.js
577 :declare
578 :function require
579 param moduleNames
580 :[
581 :string
582 param onLoad
583 :=>
584 :void
585 param ...args
586 :[
587 :any
588 :return
589 :void
590 import
591 as Zip
592 from "./ZipCodeValidator"
593 if needZipValidation
594 _ require
595 [
596 @ "./ZipCodeValidator"
597 =>
598 param ZipCodeValidator
599 :typeof Zip
600 let validator = new ZipCodeValidator.ZipCodeValidator()
601 if validator.isAcceptable("...")
602 #
603 # Sample: Dynamic Module Loading in System.js
604 :declare
605 const System
606 :any
607 import
608 @ ZipCodeValidator
609 as Zip
610 from "./ZipCodeValidator"
611 if needZipValidation
612 _ System.import("./ZipCodeValidator").then
613 =>
614 param ZipCodeValidator
615 :typeof Zip
616 var x = new ZipCodeValidator()
617 if x.isAcceptable("...")
618 item
619 title Ambient Modules
620 expected
621 + /* node.d.ts(simplified excerpt) */
622 + declare module "url" {
623 + export interface Url {
624 + protocol?: string;
625 + hostname?: string;
626 + pathname?: string;
627 + }
628 + export function parse(urlStr: string, parseQueryString?, slashesDenoteHost?): Url;
629 + }
630 + declare module "path" {
631 + export function normalize(p: string): string;
632 + export function join(...paths: any[]): string;
633 + export var sep: string;
634 + }
635 + /* Now we can /// <reference> node.d.ts and then load the modules using import url = require("url"); or import * as URL from "url". */
636 + /// <reference path="node.d.ts"/>
637 + import * as URL from "url";
638 + let myUrl = URL.parse("http://www.typescriptlang.org");
639 ittf
640 +
641 #
642 # node.d.ts(simplified excerpt)
643 :declare
644 :module "url"
645 export
646 :interface Url
647 :p protocol
648 :optional
649 :string
650 :p hostname
651 :optional
652 :string
653 :p pathname
654 :optional
655 :string
656 export
657 :function parse
658 param urlStr
659 :string
660 param parseQueryString
661 :optional
662 param slashesDenoteHost
663 :optional
664 :return
665 :ref Url
666 :module "path"
667 export
668 :function normalize
669 param p
670 :string
671 :return
672 :string
673 export
674 :function join
675 param ...paths
676 :[
677 :any
678 :return
679 :string
680 export
681 var sep
682 :string
683 #
684 # Now we can /// <reference> node.d.ts and then load the modules using import url = require("url"); or import * as URL from "url".
685 import
686 as URL
687 from "url"
688 let myUrl = URL.parse("http://www.typescriptlang.org")
689 item
690 title Shorthand ambient modules
691 expected
692 + /*declarations.d.ts */
693 + declare module "hot-new-module";
694 + /* All imports from a shorthand module will have the any type. */
695 + import x, { y } from "hot-new-module";
696 + x(y);
697 ittf
698 +
699 #
700 # declarations.d.ts
701 :declare
702 :module "hot-new-module"
703 #
704 # All imports from a shorthand module will have the any type.
705 import x
706 @ y
707 from "hot-new-module"
708 _ x(y)
709 item
710 title Wildcard module declarations
711 expected
712 + declare module "*!text" {
713 + const content: string;
714 + export default content;
715 + }
716 + // Some do it the other way around.
717 + declare module "json!*" {
718 + const value: any;
719 + export default value;
720 + }
721 + /* Now you can import things that match "*!text" or "json!*". */
722 + import fileContent from "./xyz.txt!text";
723 + import data from "json!http://example.com/data.json";
724 + console.log(data, fileContent);
725 ittf
726 +
727 :declare
728 :module "*!text"
729 const content
730 :string
731 export-default content
732 :module "json!*"
733 const value
734 :any
735 export-default value
736 #
737 # Now you can import things that match "*!text" or "json!*".
738 import fileContent from "./xyz.txt!text"
739 import data from "json!http://example.com/data.json"
740 _ console.log(data, fileContent)
741 item
742 title UMD modules
743 expected
744 + /* math-lib.d.ts */
745 + export function isPrime(x: number): boolean;
746 + export as namespace mathLib;
747 + /* The library can then be used as an import within modules: */
748 + import { isPrime } from "math-lib";
749 + isPrime(2);
750 + mathLib.isPrime(2); // ERROR: can't use the global definition from inside a module
751 + /* It can also be used as a global variable, but only inside of a script. (A script is a file with no imports or exports.) */
752 + mathLib.isPrime(2);
753 ittf
754 +
755 #
756 # math-lib.d.ts
757 export
758 :function isPrime
759 param x
760 :number
761 :return
762 :boolean
763 :export-ns mathLib
764 #
765 # The library can then be used as an import within modules:
766 import
767 @ isPrime
768 from "math-lib"
769 _ isPrime(2)
770 _ mathLib.isPrime(2)
771 #
772 # It can also be used as a global variable, but only inside of a script. (A script is a file with no imports or exports.)
773 _ mathLib.isPrime(2)
774 item
775 title Export as close to top-level as possible
776 expected
777 + MyClass.ts */
778 + export default class SomeType {
779 + constructor() {}
780 + }
781 + /* MyFunc.ts */
782 + export default function getThing() { return "thing"; }
783 + /* Consumer.ts */
784 + import t from "./MyClass";
785 + import f from "./MyFunc";
786 + let x = new t();
787 + console.log(f());
788 + /* MyThings.ts */
789 + export class SomeType { /* ... */ }
790 + export function someFunc() { /* ... */ }
791 + /* Consumer.ts */
792 + import { SomeType, someFunc } from "./MyThings";
793 + let x = new SomeType();
794 + let y = someFunc();
795 + /* MyLargeModule.ts */
796 + export class Dog { }
797 + export class Cat { }
798 + export class Tree { }
799 + export class Flower { }
800 + /* Consumer.ts */
801 + import * as myLargeModule from "./MyLargeModule.ts";
802 + let x = new myLargeModule.Dog();
803 ittf
804 +
805 export-default
806 class SomeType
807 ctor
808 #
809 # MyFunc.ts
810 export-default
811 function getThing
812 return "thing"
813 #
814 # Consumer.ts
815 import t from "./MyClass"
816 import f from "./MyFunc"
817 let x = new t()
818 _ console.log(f())
819 #
820 # This is optimal for consumers.
821 # They can name your type whatever they want (t in this case) and don’t have to do any excessive dotting to find your objects.
822 # If you’re exporting multiple objects, put them all at top- level
823 # MyThings.ts
824 export
825 class SomeType
826 export
827 function someFunc
828 #
829 # Conversely when importing:
830 # Explicitly list imported names
831 # Consumer.ts
832 import
833 @ SomeType
834 @ someFunc
835 from "./MyThings"
836 let x = new SomeType()
837 let y = someFunc()
838 #
839 # Use the namespace import pattern if you’re importing a large number of things
840 # MyLargeModule.ts
841 export
842 class Dog
843 export
844 class Cat
845 export
846 class Tree
847 export
848 class Flower
849 #
850 # Consumer.ts
851 import
852 as myLargeModule
853 from "./MyLargeModule.ts"
854 let x = new myLargeModule.Dog()
855 item
856 title Re -export to extend
857 expected
858 + export class Calculator {
859 + private current = 0;
860 + private memory = 0;
861 + private operator: string;
862 + protected processDigit(digit: string, currentValue: number) {
863 + if (digit >= "0" && digit <= "9") {
864 + return currentValue * 10 + (digit.charCodeAt(0) - "0".charCodeAt(0));
865 + }
866 + }
867 + protected processOperator(operator: string) {
868 + if (["+", "-", "*", "/"].indexOf(operator) >= 0) {
869 + return operator;
870 + }
871 + }
872 + protected evaluateOperator(operator: string, left: number, right: number): number {
873 + switch (this.operator) {
874 + case "+": return left + right;
875 + case "-": return left - right;
876 + case "*": return left * right;
877 + case "/": return left / right;
878 + }
879 + }
880 + private evaluate() {
881 + if (this.operator) {
882 + this.memory = this.evaluateOperator(this.operator, this.memory, this.current);
883 + } else {
884 + this.memory = this.current;
885 + }
886 + this.current = 0;
887 + }
888 + public handleChar(char: string) {
889 + if (char === "=") {
890 + this.evaluate();
891 + return;
892 + } else {
893 + let value = this.processDigit(char, this.current);
894 + if (value !== undefined) {
895 + this.current = value;
896 + return;
897 + } else {
898 + let value = this.processOperator(char);
899 + if (value !== undefined) {
900 + this.evaluate();
901 + this.operator = value;
902 + return;
903 + }
904 + }
905 + }
906 + throw new Error(`Unsupported input: '${char}'`);
907 + }
908 + public getResult() {
909 + return this.memory;
910 + }
911 + }
912 + export function test(c: Calculator, input: string) {
913 + for (let i = 0; i < input.length; i++) {
914 + c.handleChar(input[i]);
915 + }
916 + console.log(`result of '${input}' is '${c.getResult()}'`);
917 + }
918 + /* Here is a simple test for the calculator using the exposed test function. */
919 + /* TestCalculator.ts */
920 + import { Calculator, test } from "./Calculator";
921 + let c = new Calculator();
922 + test(c, "1+2*33/11="); // prints 9
923 + /* Now to extend this to add support for input with numbers in bases other than 10, let’s create ProgrammerCalculator.ts
924 + /* ProgrammerCalculator.ts */
925 + import { Calculator } from "./Calculator";
926 + class ProgrammerCalculator extends Calculator {
927 + static digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
928 + constructor(public base: number) {
929 + super();
930 + const maxBase = ProgrammerCalculator.digits.length;
931 + if (base <= 0 || base > maxBase) {
932 + throw new Error(`base has to be within 0 to ${maxBase} inclusive.`);
933 + }
934 + }
935 + protected processDigit(digit: string, currentValue: number) {
936 + if (ProgrammerCalculator.digits.indexOf(digit) >= 0) {
937 + return currentValue * this.base + ProgrammerCalculator.digits.indexOf(digit);
938 + }
939 + }
940 + }
941 + // Export the new extended calculator as Calculator
942 + export { ProgrammerCalculator as Calculator };
943 + // Also, export the helper function
944 + export { test } from "./Calculator";
945 + /* TestProgrammerCalculator.ts */
946 + import { Calculator, test } from "./ProgrammerCalculator";
947 + let c = new Calculator(2);
948 + test(c, "001+010="); // prints 3
949 ittf
950 +
951 export
952 class Calculator
953 p current
954 :private
955 := 0
956 p memory
957 :private
958 := 0
959 p operator
960 :private
961 :string
962 m processDigit
963 :protected
964 param digit
965 :string
966 param currentValue
967 :number
968 if digit >= "0" && digit <= "9"
969 return currentValue * 10 + (digit.charCodeAt(0) - "0".charCodeAt(0))
970 m processOperator
971 :protected
972 param operator
973 :string
974 if
975 test
976 >=
977 [
978 @ "+"
979 @ "-"
980 @ "*"
981 @ "/"
982 ._ indexOf
983 @ operator
984 + 0
985 return operator
986 m evaluateOperator
987 :protected
988 param operator
989 :string
990 param left
991 :number
992 param right
993 :number
994 :return
995 :number
996 switch this.operator
997 case "+"
998 return left + right
999 case "-"
1000 return left - right
1001 case "*"
1002 return left * right
1003 case "/"
1004 return left / right
1005 m evaluate
1006 :private
1007 if this.operator
1008 set this.memory = this.evaluateOperator(this.operator, this.memory, this.current)
1009 else
1010 set this.memory = this.current
1011 set this.current = 0
1012 m handleChar
1013 :public
1014 param char
1015 :string
1016 if char === "="
1017 _ this.evaluate
1018 return
1019 else
1020 let value = this.processDigit(char, this.current)
1021 if value !== undefined
1022 set this.current = value
1023 return
1024 else
1025 let value = this.processOperator(char)
1026 if value !== undefined
1027 _ this.evaluate
1028 set this.operator = value
1029 return
1030 throw
1031 new Error
1032 template
1033 + Unsupported input: '
1034 @ char
1035 + '
1036 m getResult
1037 :public
1038 return this.memory
1039 export
1040 function test
1041 param c
1042 :ref Calculator
1043 param input
1044 :string
1045 for let i = 0; i < input.length; i++
1046 _ c.handleChar(input[i])
1047 _ console.log
1048 template
1049 + result of '
1050 @ input
1051 + ' is '
1052 _ c.getResult
1053 + '
1054 #
1055 # Here is a simple test for the calculator using the exposed test function.
1056 #
1057 # TestCalculator.ts
1058 import
1059 @ Calculator
1060 @ test
1061 from "./Calculator"
1062 let c = new Calculator()
1063 _ test(c, "1+2*33/11=")
1064 #
1065 # Now to extend this to add support for input with numbers in bases other than 10, let’s create ProgrammerCalculator.ts
1066 # ProgrammerCalculator.ts
1067 import
1068 @ Calculator
1069 from "./Calculator"
1070 class ProgrammerCalculator
1071 super Calculator
1072 p digits
1073 static
1074 [
1075 @ "0"
1076 @ "1"
1077 @ "2"
1078 @ "3"
1079 @ "4"
1080 @ "5"
1081 @ "6"
1082 @ "7"
1083 @ "8"
1084 @ "9"
1085 @ "A"
1086 @ "B"
1087 @ "C"
1088 @ "D"
1089 @ "E"
1090 @ "F"
1091 ctor
1092 param base
1093 :public
1094 :number
1095 _ super
1096 const maxBase = ProgrammerCalculator.digits.length
1097 if base <= 0 || base > maxBase
1098 throw
1099 new Error
1100 template
1101 + base has to be within 0 to${}
1102 @ maxBase
1103 + ${}inclusive.
1104 m processDigit
1105 :protected
1106 param digit
1107 :string
1108 param currentValue
1109 :number
1110 if ProgrammerCalculator.digits.indexOf(digit) >= 0
1111 return currentValue * this.base + ProgrammerCalculator.digits.indexOf(digit)
1112 export
1113 @ ProgrammerCalculator
1114 as Calculator
1115 export
1116 @ test
1117 from "./Calculator"
1118 #
1119 # The new module ProgrammerCalculator exports an API shape similar to that of the original Calculator module,
1120 # but does not augment any objects in the original module. Here is a test for our ProgrammerCalculator class:
1121 # TestProgrammerCalculator.ts
1122 import
1123 @ Calculator
1124 @ test
1125 from "./ProgrammerCalculator"
1126 let c = new Calculator(2)
1127 _ test(c, "001+010=")