Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Typescript 2.6 #367

Merged
merged 22 commits into from Nov 30, 2017
Merged

Typescript 2.6 #367

merged 22 commits into from Nov 30, 2017

Conversation

bryanforbes
Copy link
Member

Type: enhancement

The following has been addressed in the PR:

  • There is a related issue
  • All code matches the style guide
  • Unit or Functional tests are included in the PR

Description:

Relates to dojo/meta#210

Copy link
Member

@agubler agubler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few questions


emit<E extends EventObject>(event: E): void {
super.emit(event);
(function (proto) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come this is needed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, couldn't something like this be accomplished with the mixin pattern?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into the mixin pattern

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is left-over from when the signature of emit and on were much more complex than they are now and I was trying to avoid repeating the signatures in QueingEvented. I've fixed these up locally to be methods on QueingEvented.

const handles = Object.keys(listenerMapArg).map((type) => this.on(type, listenerMapArg[type]));
on<K extends keyof M>(type: K, listener: EventedCallbackOrArray<K, M[K]>): Handle;
on(type: T, listener: EventedCallbackOrArray<T, O>): Handle;
on(type: any, listener: EventedCallbackOrArray<any, any>): Handle {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assume this can't be T | K?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. K and T need to be specifically associated with the correct EventedCallbackOrArray. Using a union type means that T could be associated with EventedCallbackOrArray<K, M[K]> which we don't want.

src/Evented.ts Outdated
// The following member is purely so TypeScript remembers the type of `M` when extending so
// that the utilities in `on.ts` will work
// tslint:disable-next-line
protected __typeMap__?: M;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems is a bit hacky :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, feels dirty to me too... 😢

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's dirty, but I'm not sure if there's any other way. TypeScript isn't able to remember the type map for use with the stand-alone on() function without it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've filed an issue with a reduced test case outlining this problem. It feels like a bug.

src/Evented.ts Outdated
this.listenersMap.forEach((method, type) => {
if (isGlobMatch(type, event.type)) {
if (isGlobMatch(<any> type, event.type)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need <any> here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, lets try to comment whenever we have to cast as any (as well as prefer the type as any instead of the arrow brackets.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because type is a generic that can be anything and isGlobMatch() requires string | symbol. Also, casting type to string | symbol doesn't work either.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's try to comment whenever we have to cast as any

As in, add a comment to code for future generations, please.

this.listenersMap.forEach((method, type) => {
if (isGlobMatch(type, event.type)) {
hasMatch = true;
}
});

if (!hasMatch) {
// @ts-ignore
let queue = this._queue.get(event.type);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are we ignoring here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, we really should comment why we are deciding to ignore something and would much prefer casting (and a comment)... I have yet to see a valid use case yet for // @ts-ignore in our code base.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were because _queue and listenersMap weren't accessible outside of the class declaration of QueuingEvented. Since I've moved the functions into the class definition, these comments are no longer needed.

if (Date.now() - milliseconds > start) {
return Promise.reject<T>(reason);
}
if (typeof value === 'function') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this new functionality?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like it's covered in tests

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not new functionality (value was T | (() => T | Thenable<T>) before my changes), but it wasn't handled properly before. You're right that we need to test it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests have been added

@agubler agubler requested a review from kitsonk November 27, 2017 08:32
@agubler
Copy link
Member

agubler commented Nov 27, 2017

Would be great if @kitsonk could also review

const { handles } = this;
handles.push(handle);
own(handles: Handle | Handle[]): Handle {
const handle = Array.isArray(handles) ? createCompositeHandle(...handles) : handles;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing a test branch here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests added

handles.push(handle);
own(handles: Handle | Handle[]): Handle {
const handle = Array.isArray(handles) ? createCompositeHandle(...handles) : handles;
const { handles: _handles } = this;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the rename?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Locally, handles is Handle | Handle[] and this.handles is Handle[]. Assigning works fine initially, but when it gets into the destroy() function returned, the compiler reverts to thinking that handles is Handle | Handle[] and requires a cast. I thought a rename was cleaner than a cast.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

src/Evented.ts Outdated
// The following member is purely so TypeScript remembers the type of `M` when extending so
// that the utilities in `on.ts` will work
// tslint:disable-next-line
protected __typeMap__?: M;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, feels dirty to me too... 😢

src/Evented.ts Outdated
this.listenersMap.forEach((method, type) => {
if (isGlobMatch(type, event.type)) {
if (isGlobMatch(<any> type, event.type)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, lets try to comment whenever we have to cast as any (as well as prefer the type as any instead of the arrow brackets.


emit<E extends EventObject>(event: E): void {
super.emit(event);
(function (proto) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, couldn't something like this be accomplished with the mixin pattern?

@@ -4,7 +4,7 @@ const { registerSuite } = intern.getInterface('object');
const { assert } = intern.getPlugin('chai');
import * as sinon from 'sinon';
import * as aspect from '../../src/aspect';
import { Handle } from '@dojo/interfaces/core';
import { Handle } from '../../src/interfaces';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We added support for symbols, but no tests for symbols.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants