Skip to content

Commit

Permalink
refactor: remove Constructable "hack" and fix exposed typing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
BBosman committed Feb 24, 2019
1 parent 463bcbc commit a2cd624
Show file tree
Hide file tree
Showing 20 changed files with 59 additions and 62 deletions.
2 changes: 1 addition & 1 deletion packages/jit-html/test/integration/util.ts
Expand Up @@ -47,7 +47,7 @@ export function setup(ctx: HTMLTestContext, template: string | Node, $class: Con
const host = ctx.createElement('app');
const au = new Aurelia(container);
const App = CustomElementResource.define({ name: 'app', template }, $class);
const component = new App();
const component = new App() as any;

return { container, lifecycle, host, au, component, observerLocator };
}
Expand Down
7 changes: 4 additions & 3 deletions packages/jit/src/binding-command.ts
Expand Up @@ -62,11 +62,12 @@ function isType<T>(this: IBindingCommandResource, Type: T & Partial<IBindingComm
function define<T extends Constructable>(this: IBindingCommandResource, name: string, ctor: T): T & IBindingCommandType;
function define<T extends Constructable>(this: IBindingCommandResource, definition: IBindingCommandDefinition, ctor: T): T & IBindingCommandType;
function define<T extends Constructable>(this: IBindingCommandResource, nameOrDefinition: string | IBindingCommandDefinition, ctor: T): T & IBindingCommandType {
const Type = ctor as T & Writable<IBindingCommandType>;
const Type = ctor as T & IBindingCommandType;
const WritableType = Type as T & Writable<IBindingCommandType>;
const description = typeof nameOrDefinition === 'string' ? { name: nameOrDefinition, target: null } : nameOrDefinition;

Type.kind = BindingCommandResource;
Type.description = description;
WritableType.kind = BindingCommandResource as IBindingCommandResource;
WritableType.description = description;
Type.register = register;

return Type;
Expand Down
33 changes: 18 additions & 15 deletions packages/kernel/src/di.ts
Expand Up @@ -102,6 +102,9 @@ if (!('getOwnMetadata' in Reflect)) {
return function(target: Function): void {
(target as IIndexable)[metadataKey] = metadataValue;
};
} as (metadataKey: any, metadataValue: any) => {
(target: Function): void;
(target: Object, propertyKey: string | symbol): void;
};
}
// tslint:enable:no-any ban-types
Expand Down Expand Up @@ -575,7 +578,7 @@ export class Container implements IContainer {
if (isRegistry(current)) {
current.register(this);
} else if (isClass(current)) {
Registration.singleton(current, current).register(this);
Registration.singleton(current, current as Constructable).register(this);
} else {
keys = Object.keys(current);
j = 0;
Expand Down Expand Up @@ -841,49 +844,49 @@ function buildAllResponse(resolver: IResolver, handler: IContainer, requestor: I
/** @internal */
export const classInvokers: IInvoker[] = [
{
invoke<T extends Constructable, K>(container: IContainer, Type: T): K {
return new Type();
invoke<T extends Constructable<T>>(container: IContainer, Type: T): InstanceType<T> {
return new Type() as InstanceType<T>;
},
invokeWithDynamicDependencies
},
{
invoke<T extends Constructable, K>(container: IContainer, Type: T, deps: Key<unknown>[]): K {
return new Type(container.get(deps[0]));
invoke<T extends Constructable<T>>(container: IContainer, Type: T, deps: Key<unknown>[]): InstanceType<T> {
return new Type(container.get(deps[0])) as InstanceType<T>;
},
invokeWithDynamicDependencies
},
{
invoke<T extends Constructable, K>(container: IContainer, Type: T, deps: Key<unknown>[]): K {
return new Type(container.get(deps[0]), container.get(deps[1]));
invoke<T extends Constructable<T>>(container: IContainer, Type: T, deps: Key<unknown>[]): InstanceType<T> {
return new Type(container.get(deps[0]), container.get(deps[1])) as InstanceType<T>;
},
invokeWithDynamicDependencies
},
{
invoke<T extends Constructable, K>(container: IContainer, Type: T, deps: Key<unknown>[]): K {
return new Type(container.get(deps[0]), container.get(deps[1]), container.get(deps[2]));
invoke<T extends Constructable<T>>(container: IContainer, Type: T, deps: Key<unknown>[]): InstanceType<T> {
return new Type(container.get(deps[0]), container.get(deps[1]), container.get(deps[2])) as InstanceType<T>;
},
invokeWithDynamicDependencies
},
{
invoke<T extends Constructable, K>(container: IContainer, Type: T, deps: Key<unknown>[]): K {
invoke<T extends Constructable<T>>(container: IContainer, Type: T, deps: Key<unknown>[]): InstanceType<T> {
return new Type(
container.get(deps[0]),
container.get(deps[1]),
container.get(deps[2]),
container.get(deps[3])
);
) as InstanceType<T>;
},
invokeWithDynamicDependencies
},
{
invoke<T extends Constructable, K>(container: IContainer, Type: T, deps: Key<unknown>[]): K {
invoke<T extends Constructable<T>>(container: IContainer, Type: T, deps: Key<unknown>[]): InstanceType<T> {
return new Type(
container.get(deps[0]),
container.get(deps[1]),
container.get(deps[2]),
container.get(deps[3]),
container.get(deps[4])
);
) as InstanceType<T>;
},
invokeWithDynamicDependencies
}
Expand All @@ -896,12 +899,12 @@ export const fallbackInvoker: IInvoker = {
};

/** @internal */
export function invokeWithDynamicDependencies<T extends Constructable, K>(
export function invokeWithDynamicDependencies<T extends Constructable<T>>(
container: IContainer,
Type: T,
staticDependencies: Key<unknown>[],
dynamicDependencies: Key<unknown>[]
): K {
): InstanceType<T> {
let i = staticDependencies.length;
let args: Key<unknown>[] = new Array(i);
let lookup: Key<unknown>;
Expand Down
11 changes: 5 additions & 6 deletions packages/kernel/src/interfaces.ts
Expand Up @@ -66,8 +66,8 @@ export interface IDisposable {
}

export type Constructable<T = {}> = {
// tslint:disable-next-line:no-any no-useless-intersection callable-types
new(...args: unknown[]): T & any; // this is a "hack" to stop typescript from nagging about the type parameter T being unused (the parameter may be used for type inference)
// tslint:disable-next-line:callable-types
new(...args: unknown[]): T;
};

export type Class<T, C = IIndexable> = C & {
Expand All @@ -84,11 +84,11 @@ export type ConstructableClass<T, C = IIndexable> = C & {
new(...args: unknown[]): T & { constructor: C };
};

export type InterfaceSymbol<T = unknown> = (target: Injectable<T>, property: string, index: number) => any;
export type InterfaceSymbol<T = unknown> = (target: Injectable<T>, property: string, index: number) => unknown;

export type InjectArray = ReadonlyArray<InterfaceSymbol | Constructable | string>;

export type Injectable<T = {}> = Constructable<T> & { inject?: (InterfaceSymbol|Constructable)[] };
export type Injectable<T = {}> = Constructable<T> & { inject?: (InterfaceSymbol | Constructable)[] };

export type IIndexable<T extends object = object> = T & { [key: string]: unknown };

Expand Down Expand Up @@ -120,8 +120,7 @@ export type Writable<T> = {

export type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];

// tslint:disable-next-line:no-any
export type Omit<T, K extends keyof T> = T extends any ? Pick<T, Exclude<keyof T, K>> : never;
export type Omit<T, K extends keyof T> = T extends {} ? Pick<T, Exclude<keyof T, K>> : never;

export type Overwrite<T1, T2> = Pick<T1, Exclude<keyof T1, keyof T2>> & T2;

Expand Down
22 changes: 11 additions & 11 deletions packages/kernel/test/di.spec.ts
Expand Up @@ -1130,33 +1130,33 @@ describe(`The classInvokers object`, function () {
class Dep6 {}

it(`invoke() handles 0 deps`, function () {
const actual: InstanceType<Constructable<Foo>> = classInvokers[0].invoke(container, Foo, []);
const actual = classInvokers[0].invoke(container, Foo, []) as InstanceType<Constructable<Foo>>;
expect(actual.args.length).to.equal(0);
});

it(`invoke() handles 1 dep`, function () {
const actual: InstanceType<Constructable<Foo>> = classInvokers[1].invoke(container, Foo, [Dep1]);
const actual = classInvokers[1].invoke(container, Foo, [Dep1]) as InstanceType<Constructable<Foo>>;
expect(actual.args.length).to.equal(1);
expect(actual.args[0]).to.be.instanceof(Dep1);
});

it(`invoke() handles 2 deps`, function () {
const actual: InstanceType<Constructable<Foo>> = classInvokers[2].invoke(container, Foo, [Dep1, Dep2]);
const actual = classInvokers[2].invoke(container, Foo, [Dep1, Dep2]) as InstanceType<Constructable<Foo>>;
expect(actual.args.length).to.equal(2);
expect(actual.args[0]).to.be.instanceof(Dep1);
expect(actual.args[1]).to.be.instanceof(Dep2);
});

it(`invoke() handles 3 deps`, function () {
const actual: InstanceType<Constructable<Foo>> = classInvokers[3].invoke(container, Foo, [Dep1, Dep2, Dep3]);
const actual = classInvokers[3].invoke(container, Foo, [Dep1, Dep2, Dep3]) as InstanceType<Constructable<Foo>>;
expect(actual.args.length).to.equal(3);
expect(actual.args[0]).to.be.instanceof(Dep1);
expect(actual.args[1]).to.be.instanceof(Dep2);
expect(actual.args[2]).to.be.instanceof(Dep3);
});

it(`invoke() handles 4 deps`, function () {
const actual: InstanceType<Constructable<Foo>> = classInvokers[4].invoke(container, Foo, [Dep1, Dep2, Dep3, Dep4]);
const actual = classInvokers[4].invoke(container, Foo, [Dep1, Dep2, Dep3, Dep4]) as InstanceType<Constructable<Foo>>;
expect(actual.args.length).to.equal(4);
expect(actual.args[0]).to.be.instanceof(Dep1);
expect(actual.args[1]).to.be.instanceof(Dep2);
Expand All @@ -1165,7 +1165,7 @@ describe(`The classInvokers object`, function () {
});

it(`invoke() handles 5 deps`, function () {
const actual: InstanceType<Constructable<Foo>> = classInvokers[5].invoke(container, Foo, [Dep1, Dep2, Dep3, Dep4, Dep5]);
const actual = classInvokers[5].invoke(container, Foo, [Dep1, Dep2, Dep3, Dep4, Dep5]) as InstanceType<Constructable<Foo>>;
expect(actual.args.length).to.equal(5);
expect(actual.args[0]).to.be.instanceof(Dep1);
expect(actual.args[1]).to.be.instanceof(Dep2);
Expand Down Expand Up @@ -1205,28 +1205,28 @@ describe(`The invokeWithDynamicDependencies function`, function () {
});

it(_`handles staticDeps is ${deps}`, function () {
const actual = invokeWithDynamicDependencies(container, Foo, deps, []) as Foo;
const actual = invokeWithDynamicDependencies(container, Foo, deps, []);
expect(actual.args).to.deep.equal(deps.map(d => `static${d}`));
});

it(`handles dynamicDeps is null`, function () {
const actual = invokeWithDynamicDependencies(container, Foo, [], null) as Foo;
const actual = invokeWithDynamicDependencies(container, Foo, [], null);
expect(actual.args.length).to.equal(1);
expect(actual.args[0]).to.equal(null);
});

it(`handles dynamicDeps is undefined`, function () {
const actual = invokeWithDynamicDependencies(container, Foo, [], undefined) as Foo;
const actual = invokeWithDynamicDependencies(container, Foo, [], undefined);
expect(actual.args.length).to.equal(0);
});

it(_`handles dynamicDeps is ${deps}`, function () {
const actual = invokeWithDynamicDependencies(container, Foo, [], deps) as Foo;
const actual = invokeWithDynamicDependencies(container, Foo, [], deps);
expect(actual.args).to.deep.equal(deps);
});

it(_`handles staticDeps is ${deps} and dynamicDeps is ${deps}`, function () {
const actual = invokeWithDynamicDependencies(container, Foo, deps, deps) as Foo;
const actual = invokeWithDynamicDependencies(container, Foo, deps, deps);
expect(actual.args[0]).to.equal(`static${deps[0]}`);
expect(actual.args[1]).to.equal(`static${deps[1]}`);
expect(actual.args[2]).to.equal(`static${deps[2]}`);
Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/nav-route.ts
Expand Up @@ -78,7 +78,7 @@ export class NavRoute {
const viewportComponent = route as IViewportComponent;
instructions.push(new ViewportInstruction(viewportComponent.component, viewportComponent.viewport, viewportComponent.parameters));
} else {
instructions.push(new ViewportInstruction(route as Partial<ICustomElementType<INode>>));
instructions.push(new ViewportInstruction(route as Partial<ICustomElementType>));
}
}
return instructions;
Expand Down
2 changes: 1 addition & 1 deletion packages/router/test/e2e/layouts/src/app.ts
Expand Up @@ -17,6 +17,6 @@ import { customElement } from '../../../../../runtime';
` })
export class App {
constructor(private readonly router: Router) {
this.router.activate();
this.router.activate().catch((error: Error) => { throw error; });
}
}
2 changes: 1 addition & 1 deletion packages/runtime-html/src/dom.ts
Expand Up @@ -405,7 +405,7 @@ export class NodeSequenceFactory implements NodeSequenceFactory {
private readonly dom: IDOM;
private readonly deepClone: boolean;
private readonly node: Node;
private readonly Type: Constructable;
private readonly Type: Constructable<INodeSequence>;

constructor(dom: IDOM, markupOrNode: string | Node) {
this.dom = dom;
Expand Down
2 changes: 0 additions & 2 deletions packages/runtime-html/src/projectors.ts
Expand Up @@ -62,7 +62,6 @@ export class ShadowDOMProjector implements IElementProjector<Node> {
}
this.shadowRoot = host.attachShadow(shadowOptions);
this.host.$customElement = $customElement;
// tslint:disable-next-line:no-unnecessary-type-assertion // this is a false positive
this.shadowRoot.$customElement = $customElement as ICustomElement<ShadowRoot>;
}

Expand Down Expand Up @@ -105,7 +104,6 @@ export class ContainerlessProjector implements IElementProjector<Node> {
this.childNodes = PLATFORM.emptyArray;
}

// tslint:disable-next-line:no-unnecessary-type-assertion // this is a false positive
this.host = dom.convertToRenderLocation(host) as CustomElementHost<Node>;
this.host.$customElement = $customElement;
}
Expand Down
1 change: 0 additions & 1 deletion packages/runtime/src/binding/connectable.ts
Expand Up @@ -121,7 +121,6 @@ function connectableDecorator<TProto, TClass>(target: DecoratableConnectable<TPr
if (!proto.hasOwnProperty('observeProperty')) proto.observeProperty = observeProperty;
if (!proto.hasOwnProperty('unobserve')) proto.unobserve = unobserve;
if (!proto.hasOwnProperty('addObserver')) proto.addObserver = addObserver;
// tslint:disable-next-line:no-unnecessary-type-assertion // this is a false positive
return target as DecoratedConnectable<TProto, TClass>;
}

Expand Down
7 changes: 4 additions & 3 deletions packages/runtime/src/resources/binding-behavior.ts
Expand Up @@ -49,13 +49,14 @@ function define<T extends Constructable = Constructable>(this: IBindingBehaviorR
function define<T extends Constructable = Constructable>(this: IBindingBehaviorResource, name: string, ctor: T): T & IBindingBehaviorType<T>;
function define<T extends Constructable = Constructable>(this: IBindingBehaviorResource, nameOrDefinition: string | IBindingBehaviorDefinition, ctor: T): T & IBindingBehaviorType<T>;
function define<T extends Constructable = Constructable>(this: IBindingBehaviorResource, nameOrDefinition: string | IBindingBehaviorDefinition, ctor: T): T & IBindingBehaviorType<T> {
const Type = ctor as T & Writable<IBindingBehaviorType>;
const Type = ctor as T & IBindingBehaviorType<T>;
const WritableType = Type as T & Writable<IBindingBehaviorType<T>>;
const description = typeof nameOrDefinition === 'string'
? { name: nameOrDefinition }
: nameOrDefinition;

Type.kind = BindingBehaviorResource;
Type.description = description;
WritableType.kind = BindingBehaviorResource as IBindingBehaviorResource;
WritableType.description = description;
Type.register = register;

return Type;
Expand Down
9 changes: 5 additions & 4 deletions packages/runtime/src/resources/custom-attribute.ts
Expand Up @@ -126,12 +126,13 @@ function define<N extends INode = INode, T extends Constructable = Constructable
function define<N extends INode = INode, T extends Constructable = Constructable>(this: ICustomAttributeResource, name: string, ctor: T): T & ICustomAttributeType<N, T>;
function define<N extends INode = INode, T extends Constructable = Constructable>(this: ICustomAttributeResource, nameOrDefinition: string | IAttributeDefinition, ctor: T): T & ICustomAttributeType<N, T>;
function define<N extends INode = INode, T extends Constructable = Constructable>(this: ICustomAttributeResource, nameOrDefinition: string | IAttributeDefinition, ctor: T): T & ICustomAttributeType<N, T> {
const Type = ctor as T & Writable<ICustomAttributeType>;
const Type = ctor as T & ICustomAttributeType<N, T>;
const WritableType = Type as T & Writable<ICustomAttributeType<N, T>>;
const description = createCustomAttributeDescription(typeof nameOrDefinition === 'string' ? { name: nameOrDefinition } : nameOrDefinition, Type);
const proto: Writable<ICustomAttribute> = Type.prototype;

Type.kind = CustomAttributeResource;
Type.description = description;
WritableType.kind = CustomAttributeResource as ICustomAttributeResource;
WritableType.description = description;
Type.register = registerAttribute;

proto.$hydrate = $hydrateAttribute;
Expand Down Expand Up @@ -181,7 +182,7 @@ function define<N extends INode = INode, T extends Constructable = Constructable
proto.$nextDetached = null;
}

return Type as ICustomAttributeType & T;
return Type;
}

export const CustomAttributeResource = {
Expand Down
7 changes: 4 additions & 3 deletions packages/runtime/src/resources/custom-element.ts
Expand Up @@ -123,11 +123,12 @@ function define<N extends INode = INode, T extends Constructable = Constructable
if (!nameOrDefinition) {
throw Reporter.error(70);
}
const Type = (ctor === null ? class HTMLOnlyElement { /* HTML Only */ } : ctor) as T & Writable<ICustomElementType>;
const Type = (ctor === null ? class HTMLOnlyElement { /* HTML Only */ } : ctor) as T & ICustomElementType<N, T>;
const WritableType = Type as Writable<ICustomElementType<N, T>>;
const description = buildTemplateDefinition(Type, nameOrDefinition);
const proto: Writable<ICustomElement> = Type.prototype;

Type.kind = CustomElementResource;
WritableType.kind = CustomElementResource as ICustomElementResource;
Type.description = description;
Type.register = registerElement;

Expand Down Expand Up @@ -191,7 +192,7 @@ function define<N extends INode = INode, T extends Constructable = Constructable
proto.$nextDetached = null;
}

return Type as ICustomElementType & T;
return Type;
}

export const CustomElementResource = {
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/resources/value-converter.ts
Expand Up @@ -54,7 +54,7 @@ function define<T extends Constructable = Constructable>(this: IValueConverterRe
Type.description = description;
Type.register = register;

return Type;
return Type as T & IValueConverterType<T>;
}

export const ValueConverterResource = {
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/templating/bindable.ts
Expand Up @@ -30,7 +30,7 @@ export function bindable<T extends InstanceType<Constructable & Partial<WithBind
// - @bindable({...opts})
config.property = $prop;
}
Bindable.for($target.constructor).add(config);
Bindable.for($target.constructor as Partial<WithBindables>).add(config);
};
if (arguments.length > 1) {
// Non invocation:
Expand Down
1 change: 0 additions & 1 deletion packages/runtime/src/templating/lifecycle-bind.ts
Expand Up @@ -233,7 +233,6 @@ export function $unbindElement(this: Writable<IBindable>, flags: LifecycleFlags)
binding = binding.$prevBinding;
}

// tslint:disable-next-line:no-unnecessary-type-assertion // this is a false positive
(this.$scope as Writable<IScope>).parentScope = null;

// remove isBound and isUnbinding flags
Expand Down
4 changes: 0 additions & 4 deletions packages/runtime/test/binding/ast.spec.ts
Expand Up @@ -268,10 +268,6 @@ describe('AST', function () {
const SimpleLogicalANDList: [string, Binary][] = [
[`$36&&$37`, new Binary('&&', new AccessScope('$36'), new AccessScope('$37'))]
];
const SimpleIsLogicalANDList: [string, IsBinary][] = [
...SimpleIsEqualityList,
...SimpleLogicalANDList
];

// This forms the group Precedence.LogicalOR
const SimpleLogicalORList: [string, Binary][] = [
Expand Down

0 comments on commit a2cd624

Please sign in to comment.