From 6d12497f26b20aee08e42c36bbd22a51985c5dfa Mon Sep 17 00:00:00 2001 From: Matt Wistrand Date: Fri, 17 Mar 2017 11:05:31 -0500 Subject: [PATCH 1/3] Update basicApp example to use declare decorator Add to the basicApp example a `declare` decorator that generates a `dojo/_base/declare` constructor from a class, update the `Dialog` widget to a class that uses that decorator, and add i18n messages. --- examples/basicApp/src/app/Dialog.ts | 52 ++++++++++--------- examples/basicApp/src/app/declareDecorator.ts | 12 +++++ examples/basicApp/src/app/main.ts | 12 +---- examples/basicApp/src/app/nls/main.ts | 4 ++ examples/basicApp/tsconfig.json | 7 +-- 5 files changed, 49 insertions(+), 38 deletions(-) create mode 100644 examples/basicApp/src/app/declareDecorator.ts create mode 100644 examples/basicApp/src/app/nls/main.ts diff --git a/examples/basicApp/src/app/Dialog.ts b/examples/basicApp/src/app/Dialog.ts index 7fb2c4b..74653d9 100644 --- a/examples/basicApp/src/app/Dialog.ts +++ b/examples/basicApp/src/app/Dialog.ts @@ -1,29 +1,31 @@ -import * as declare from 'dojo/_base/declare'; -import * as Dialog from 'dijit/Dialog'; +import * as DijitDialog from 'dijit/Dialog'; +import * as messages from 'dojo/i18n!./nls/main'; +import declare from './declareDecorator'; -/* We are using the ES6 module format here, as it is more forward compatible */ +/** + * `dojo/_base/declare` can infer typings, but since we are generating our declare + * constructor with a decorator (see below), we need to define our widget interface + * explicitly. + */ +interface Dialog extends DijitDialog {} -/* While type inference works with declare, if you want to refer to the type at - * some other point, you cannot easily extract the type. Therefore we will do - * essentially what the dojo.declare typings will do and create type reference. - * This does not emit anything, but it allows others using this module in - * TypeScript to have a clear reference to the type we are creating here */ -export type DialogType = dijit.Dialog & { - title: string; - content: string; -}; +/** + * By using a decorator to create constructors with `dojo/_base/declare`, we can + * write our widgets using TypeScript classes. The one caveat is that we are then + * required to use merged declarations to define our interface, so the widget + * class has to be declared as the default export in a separate statement. + */ +declare(DijitDialog) +class Dialog { + title: string = messages.dialogTitle; + content: string = messages.dialogContent; +} -/* dojo.declare can infer the typings here, but as explained above, we want to - * specfically assert the type, so we are providing it as a generic argument - * for decalare - * - * In addition, we are using `export default` here, which is part of the ES6 - * module format. If other consumers of the module are compatible with default - * exports, like other modules written in TypeScript, then this is fine, but if - * someone consumes this module, that insead of this being the return value of - * the module, it will be located under Dialog.default. +/* + * We are using `export default` here, which is part of the ES6 module format. + * If other consumers of the module are compatible with default exports, like + * other modules written in TypeScript, then this is fine, but if someone + * consumes this module, that insead of this being the return value of the module, + * it will be located under Dialog.default. */ -export default declare(Dialog, { - title: 'Hello World', - content: 'Loaded successfully!' -}); +export default Dialog; diff --git a/examples/basicApp/src/app/declareDecorator.ts b/examples/basicApp/src/app/declareDecorator.ts new file mode 100644 index 0000000..89ebae7 --- /dev/null +++ b/examples/basicApp/src/app/declareDecorator.ts @@ -0,0 +1,12 @@ +import * as declare from 'dojo/_base/declare'; + +/** + * A decorator that converts a TypeScript class into a declare constructor. + * This allows declare constructors be defined as classes, which nicely + * hides away the `declare([], {})` boilerplate. + */ +export default function (... mixins: Object[]): ClassDecorator { + return function (target: Function) { + return declare(mixins, target.prototype); + }; +} diff --git a/examples/basicApp/src/app/main.ts b/examples/basicApp/src/app/main.ts index b7db7d1..44876d9 100644 --- a/examples/basicApp/src/app/main.ts +++ b/examples/basicApp/src/app/main.ts @@ -1,19 +1,11 @@ -import Dialog, { DialogType } from './Dialog'; +import Dialog from './Dialog'; import 'dojo/domReady!'; -/* Using just "import 'mid'"" above loads the modules for and causes the - * appropriate side affects, but doesn't create any reference in the module - * - * Also we are using the destrcuring syntax to also import a reference to the - * DialogType type above. This will not actually emit anything because there - * is no runtime emit for the type - */ - /* So others can consume our application module better under TypeScript, lets * specify an interface for our application and export it */ export interface App { - dialog: DialogType; + dialog: Dialog; } /* Now we are creating our application object */ diff --git a/examples/basicApp/src/app/nls/main.ts b/examples/basicApp/src/app/nls/main.ts new file mode 100644 index 0000000..a6b3316 --- /dev/null +++ b/examples/basicApp/src/app/nls/main.ts @@ -0,0 +1,4 @@ +export const root = { + dialogTitle: 'Hello World', + dialogContent: 'Loaded successfully!' +}; diff --git a/examples/basicApp/tsconfig.json b/examples/basicApp/tsconfig.json index 9c486a4..71df7c4 100644 --- a/examples/basicApp/tsconfig.json +++ b/examples/basicApp/tsconfig.json @@ -7,10 +7,11 @@ "sourceMap": true, "target": "ES5" }, + "include": [ + "./src/**/*.ts" + ], "files": [ - "./src/app/main.ts", - "./src/app/Dialog.ts", "../../dojo/1.11/modules.d.ts", "../../dijit/1.11/modules.d.ts" ] -} \ No newline at end of file +} From 94b4adc7623328879a6e729c112b7f075100737e Mon Sep 17 00:00:00 2001 From: Matt Wistrand Date: Fri, 17 Mar 2017 12:12:32 -0500 Subject: [PATCH 2/3] Fix typos; add experimentalDecorators to tsconfig --- examples/basicApp/src/app/Dialog.ts | 2 +- examples/basicApp/src/app/declareDecorator.ts | 2 +- examples/basicApp/src/app/main.ts | 2 +- examples/basicApp/tsconfig.json | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/basicApp/src/app/Dialog.ts b/examples/basicApp/src/app/Dialog.ts index 74653d9..725c3cf 100644 --- a/examples/basicApp/src/app/Dialog.ts +++ b/examples/basicApp/src/app/Dialog.ts @@ -15,7 +15,7 @@ interface Dialog extends DijitDialog {} * required to use merged declarations to define our interface, so the widget * class has to be declared as the default export in a separate statement. */ -declare(DijitDialog) +@declare(DijitDialog) class Dialog { title: string = messages.dialogTitle; content: string = messages.dialogContent; diff --git a/examples/basicApp/src/app/declareDecorator.ts b/examples/basicApp/src/app/declareDecorator.ts index 89ebae7..f1ab6cf 100644 --- a/examples/basicApp/src/app/declareDecorator.ts +++ b/examples/basicApp/src/app/declareDecorator.ts @@ -2,7 +2,7 @@ import * as declare from 'dojo/_base/declare'; /** * A decorator that converts a TypeScript class into a declare constructor. - * This allows declare constructors be defined as classes, which nicely + * This allows declare constructors to be defined as classes, which nicely * hides away the `declare([], {})` boilerplate. */ export default function (... mixins: Object[]): ClassDecorator { diff --git a/examples/basicApp/src/app/main.ts b/examples/basicApp/src/app/main.ts index 44876d9..59cbd43 100644 --- a/examples/basicApp/src/app/main.ts +++ b/examples/basicApp/src/app/main.ts @@ -1,7 +1,7 @@ import Dialog from './Dialog'; import 'dojo/domReady!'; -/* So others can consume our application module better under TypeScript, lets +/* So others can consume our application module better under TypeScript, let's * specify an interface for our application and export it */ export interface App { diff --git a/examples/basicApp/tsconfig.json b/examples/basicApp/tsconfig.json index 71df7c4..4d32549 100644 --- a/examples/basicApp/tsconfig.json +++ b/examples/basicApp/tsconfig.json @@ -5,7 +5,8 @@ "outDir": "_build", "removeComments": false, "sourceMap": true, - "target": "ES5" + "target": "ES5", + "experimentalDecorators": true }, "include": [ "./src/**/*.ts" From de32461423d00f82da4fdba70854c0cababa327d Mon Sep 17 00:00:00 2001 From: Matt Wistrand Date: Tue, 21 Mar 2017 12:27:28 -0500 Subject: [PATCH 3/3] Fix typo in basicApp Dialog.ts --- examples/basicApp/src/app/Dialog.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basicApp/src/app/Dialog.ts b/examples/basicApp/src/app/Dialog.ts index 725c3cf..47b70a5 100644 --- a/examples/basicApp/src/app/Dialog.ts +++ b/examples/basicApp/src/app/Dialog.ts @@ -25,7 +25,7 @@ class Dialog { * We are using `export default` here, which is part of the ES6 module format. * If other consumers of the module are compatible with default exports, like * other modules written in TypeScript, then this is fine, but if someone - * consumes this module, that insead of this being the return value of the module, + * consumes this module, that instead of this being the return value of the module, * it will be located under Dialog.default. */ export default Dialog;