Refactored knockout components

Previous Knockout component registration code was complicate since union
types did not exist in TypeScript. The knockout.d.ts file has already
had changes for union types added, so I have refactored my original
changes to component.register to use this.

Revert "Refactored knockout.register for union types"

This reverts
commit 920b8d64621f249331f2a17123148c446c212d32.

Refactored knockout.register for union types

Removed number of
interfaces for ko.register methods and simplified
using union types for
clarity. Refactored component types into a
namespace to reduce namespace
pollution
This commit is contained in:
HowardRichards
2015-03-02 12:21:01 +00:00
parent 3882d337bb
commit 4db25cf3f1
2 changed files with 102 additions and 108 deletions
+77 -81
View File
@@ -1,4 +1,4 @@
// Type definitions for Knockout v3.2.0-beta
// Type definitions for Knockout v3.2.0
// Project: http://knockoutjs.com
// Definitions by: Boris Yankov <https://github.com/borisyankov/>, Igor Oleinikov <https://github.com/Igorbek/>, Clément Bourgeois <https://github.com/moonpyk/>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
@@ -559,92 +559,88 @@ interface KnockoutBindingProvider {
getBindingAccessors?(node: Node, bindingContext: KnockoutBindingContext): { [key: string]: string; };
}
interface KnockoutComponents {
// overloads for register method:
register(componentName: string, config: KnockoutComponentRegister): void;
register(componentName: string, config: KnockoutComponentRegisterStringTemplate): void;
register(componentName: string, config: KnockoutComponentRegisterFnViewModel): void;
register(componentName: string, config: KnockoutComponentRegisterStringTemplateFnViewModel): void;
register(componentName: string, config: KnockoutComponentRegisterAMD): void;
register(componentName: string, config: {}): void;
isRegistered(componentName: string): boolean;
unregister(componentName: string): void;
get(componentName: string, callback: (definition: KnockoutComponentDefinition) => void): void;
clearCachedDefinition(componentName: string): void
defaultLoader: KnockoutComponentLoader;
loaders: KnockoutComponentLoader[];
getComponentNameForNode(node: Node): string;
}
/* interfaces for register overloads*/
interface KnockoutComponentRegister {
template: KnockoutComponentTemplate;
viewModel?: KnockoutComponentConfigViewModel;
}
interface KnockoutComponentRegisterAMD {
// load self-describing module using AMD module name
require: string;
}
interface KnockoutComponentRegisterFnViewModel {
template: KnockoutComponentTemplate;
viewModel?: (params: any) => any;
}
interface KnockoutComponentRegisterStringTemplate {
template: string;
viewModel?: KnockoutComponentConfigViewModel;
}
interface KnockoutComponentRegisterStringTemplateFnViewModel {
template: string;
viewModel?: (params: any) => any;
}
interface KnockoutComponentConfigViewModel {
instance?: any;
createViewModel? (params?: any, componentInfo?: KnockoutComponentInfo): any;
require?: string;
}
interface KnockoutComponentTemplate {
// specify element id (string) or a node
element?: any;
// AMD module load
require?: string;
}
interface KnockoutComponentInfo {
element: Node;
}
/* end register overloads */
interface KnockoutComponentDefinition {
template: Node[];
createViewModel?(params: any, options: { element: Node; }): any;
}
interface KnockoutComponentLoader {
getConfig? (componentName: string, callback: (result: KnockoutComponentConfig) => void): void;
loadComponent? (componentName: string, config: KnockoutComponentConfig, callback: (result: KnockoutComponentDefinition) => void): void;
loadTemplate? (componentName: string, templateConfig: any, callback: (result: Node[]) => void): void;
loadViewModel? (componentName: string, viewModelConfig: any, callback: (result: any) => void): void;
suppressLoaderExceptions?: boolean;
}
interface KnockoutComponentConfig {
template: any;
createViewModel?: any;
}
interface KnockoutComputedContext {
getDependenciesCount(): number;
isInitial: () => boolean;
isSleeping: boolean;
}
//
// refactored types into a namespace to reduce global pollution
// and used Union Types to simplify overloads (requires TypeScript 1.4)
//
declare module KnockoutComponentTypes {
interface Config {
viewModel: ViewModelFunction | ViewModelSharedInstance | ViewModelFactoryFunction | AMDModule;
template: string | Node[]| DocumentFragment | TemplateElement | AMDModule;
}
interface ComponentConfig {
template: any;
createViewModel?: any;
}
interface EmptyConfig {
}
// common AMD type
interface AMDModule {
require: string;
}
// viewmodel types
interface ViewModelFunction {
(params?: any): any;
}
interface ViewModelSharedInstance {
instance: any;
}
interface ViewModelFactoryFunction {
createViewModel: (params?: any, componentInfo?: ComponentInfo) => any;
}
interface ComponentInfo {
element: any;
}
interface TemplateElement {
element: string | Node;
}
interface Loader {
getConfig? (componentName: string, callback: (result: ComponentConfig) => void): void;
loadComponent? (componentName: string, config: ComponentConfig, callback: (result: Definition) => void): void;
loadTemplate? (componentName: string, templateConfig: any, callback: (result: Node[]) => void): void;
loadViewModel? (componentName: string, viewModelConfig: any, callback: (result: any) => void): void;
suppressLoaderExceptions?: boolean;
}
interface Definition {
template: Node[];
createViewModel? (params: any, options: { element: Node; }): any;
}
}
interface KnockoutComponents {
// overloads for register method:
register(componentName: string, config: KnockoutComponentTypes.Config | KnockoutComponentTypes.EmptyConfig): void;
isRegistered(componentName: string): boolean;
unregister(componentName: string): void;
get(componentName: string, callback: (definition: KnockoutComponentTypes.Definition) => void): void;
clearCachedDefinition(componentName: string): void
defaultLoader: KnockoutComponentTypes.Loader;
loaders: KnockoutComponentTypes.Loader[];
getComponentNameForNode(node: Node): string;
}
declare module "knockout" {
export = ko;
}
+25 -27
View File
@@ -604,52 +604,50 @@ function test_allBindingsAccessor() {
};
}
function test_Components() {
// test all possible ko.components.register() overloads
function test_Register() {
// test all possible ko.components.register() overloads
// reused parameters
var nodeArray = [new Node, new Node];
var singleNode = new Node;
var viewModelFn = function (params: any) { return <any>null; }
// ------- string-templates with different viewmodel overloads:
// ------- viewmodel overloads:
// string template and inline function (commonly used in examples)
ko.components.register("name", { template: "string-template", viewModel: function (params) { return null; } });
// viewModel as inline function (commonly used in examples)
ko.components.register("name", { template: "string-template", viewModel: viewModelFn });
// string template and instance vm
// viewModel from shared instance
ko.components.register("name", { template: "string-template", viewModel: { instance: null } });
// string template and createViewModel factory method
ko.components.register("name", { template: "string-template", viewModel: { createViewModel: function (params: any, componentInfo: KnockoutComponentInfo) { return null; } } });
// viewModel from createViewModel factory method
ko.components.register("name", { template: "string-template", viewModel: { createViewModel: function (params: any, componentInfo: KnockoutComponentTypes.ComponentInfo) { return null; } } });
// string template and require module vm
// viewModel from an AMD module
ko.components.register("name", { template: "string-template", viewModel: { require: "module" } });
// ------- non-string templates
// ------- template overloads
// viewmodel as function and four types of template
ko.components.register("name", { template: { element: "elementID" }, viewModel: function (params) { return null; } });
// Node template for element and inline function (commonly used in examples)
ko.components.register("name", { template: { element: singleNode }, viewModel: function (params) { return null; } });
// object template for element and inline function (commonly used in examples)
ko.components.register("name", { template: nodeArray, viewModel: function (params) { return null; } });
// object template for element and inline function (commonly used in examples)
ko.components.register("name", { template: { require: "module" }, viewModel: function (params) { return null; } });
// viewmodel as object, and four types of non-string tempalte
ko.components.register("name", { template: { element: "elementID" }, viewModel: { instance: null } });
// Node template for element and inline function (commonly used in examples)
ko.components.register("name", { template: { element: singleNode }, viewModel: { instance: null } });
// object template for element and inline function (commonly used in examples)
ko.components.register("name", { template: nodeArray, viewModel: { instance: null } });
// object template for element and inline function (commonly used in examples)
ko.components.register("name", { template: { require: "module" }, viewModel: { instance: null } });
// template from named element
ko.components.register("name", { template: { element: "elementID" }, viewModel: viewModelFn });
// template using single Node
ko.components.register("name", { template: { element: singleNode }, viewModel: viewModelFn });
// template using Node array
ko.components.register("name", { template: nodeArray, viewModel: viewModelFn });
// template using an AMD module
ko.components.register("name", { template: { require: "text!module" }, viewModel: viewModelFn });
// Empty config for registering custom elements that are handled by name convention
ko.components.register('name', { /* No config needed */ });
ko.components.register('name', { /* No config needed */ });
}
}
function testUnwrapUnion() {
var possibleObs: KnockoutObservable<number> | number;