-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add TypeScript declarations. #4928
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe move all the d.ts
files to a types
folder?
gulpfile.js
Outdated
@@ -267,8 +267,18 @@ gulp.task('generate-externs', ['clean'], () => { | |||
}); | |||
}); | |||
|
|||
gulp.task('generate-typescript', () => { | |||
let genTs = require('@polymer/gen-typescript-declarations').generateDeclarations; | |||
del.sync(['**/*.d.ts']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use promise api with del
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(async/await ftw)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
I think siblings makes sense, especially with the move to modules coming up. /cc @FredKSchott and @usergenic because we'll need modulizer to re-generate the types. |
@justinfagnani I'm fine with that, but note that once we're on modules, we'll also be on NPM, so we can and should add types as part of I think the objection to sibling files from @azakus is that it clutters up the source repo. Siblings for 2.0 is simpler from my perspective, but I understand not wanting to clutter the repo. Can you elaborate on how this will work with modulizer? I would have thought we'd just blow away the 2.0 types before we run modulizer, and re-run the generator afterwards, once it has support for modules? |
I have updated the description to reference #4025 which this PR fixes as well. |
28a8603
to
9c00f7e
Compare
86d7a99
to
23fe44a
Compare
Annotate that dedupingMixin returns T.
23fe44a
to
1ef2cec
Compare
Includes hand written types for cases that couldn't be generated. Uses https://github.com/Polymer/gen-typescript-declarations. Run with `gulp generate-typescript`. Also asyncify the gulpfile with fs-extra.
1ef2cec
to
60450bf
Compare
Hi all. This is ready for another look. Highly recommend reviewing the 3 commits separately.
|
Also, this now includes the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a note that we now require Node 8 in the README?
Generally LGTM, minus that nit and need to double-check closure with return type on deduping mixin.
lib/utils/mixin.html
Outdated
@@ -38,6 +38,7 @@ | |||
* @memberof Polymer | |||
* @template T | |||
* @param {T} mixin ES6 class expression mixin to wrap | |||
* @return {T} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I remember, the magic voodoo that Closure Compiler uses for mixins doesn't like a return type here. Can you double check that gulp lint-closure
doesn't produce any warnings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a note that we now require Node 8 in the README?
Added some items to the CHANGELOG. Where should I mention the Node version in the README? It doesn't currently mention the gulp script. (async/await was actually 7.6 btw).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I remember, the magic voodoo that Closure Compiler uses for mixins doesn't like a return type here. Can you double check that gulp lint-closure doesn't produce any warnings?
I ran gulp lint
, and it produces a lot of warnings. Nothing about dedupingMixin
that I can see, though. Here's the log, does it look normal?: https://gist.github.com/aomarks/3adb586df000a36e682cc4f87137606b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Closure is compiling cleanly now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a couple of questions regarding the return types of several methods.
Most notably, I see several methods that have void|null
, where the code has no return statement and therefore should be just void
.
Also there are several callbacks that have return type any
, but the element definitions do not define a return type for these methods.
(Is there a reason these callbacks are typed anyways, as it seems they are only included if they are specified if the element uses them)
I am not sure if the overall goal is 100% type-correct, but as a TypeScript user I would expect the types to be as specific as possible.
Therefore if methods do not return anything, void
is more specific than any
.
Since all of the types are generated, I am not sure if this is a bug in the gen-typescript-declarations or that our Closure types are wrong.
To summarize the other points:
- Change
void|null
tovoid
- Change
any
tovoid
for return types where functions do not return anything - Change
X|null
to justX
(for most of the cases) - Unify all callback declarations to 1 class that everyone extends, probably just in
property-accessors.d.ts
, which is the lowest entry-point - Some other small comments in relation to specific functions
- Remove
|null
when argument is already optional withX?
Sorry for the many comments, but I am really excited for this change! Just would like to be as specific as possible and not "lie" through our types 😂
*/ | ||
function ArraySelectorMixin<T extends new(...args: any[]) => {}>(base: T): { | ||
new(...args: any[]): ArraySelectorMixin & Polymer.ElementMixin | ||
} & T |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is some nice TypeScript voodo 👌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these would be easier to read if you define the Constructor<T>
type.
/** | ||
* Clears the selection state. | ||
*/ | ||
clearSelection(): any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be void
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added @returns
annotation.
* | ||
* @param item Item from `items` array to deselect | ||
*/ | ||
deselect(item: any): void|null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should just be void
. I do not see a return statement in this method that returns null
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Fixed nullable void bug in Polymer/gen-typescript-declarations#40.
types/lib/elements/dom-bind.d.ts
Outdated
*/ | ||
attributeChangedCallback(): any; | ||
connectedCallback(): any; | ||
disconnectedCallback(): any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All these methods are defined on HTMLElement
which should be void
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added @returns
annotation.
types/lib/elements/dom-module.d.ts
Outdated
* let img = customElements.get('dom-module').import('foo', 'img'); | ||
*/ | ||
class DomModule extends HTMLElement { | ||
attributeChangedCallback(name: any, old: any, value: any): any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name
can be string
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added @param
annotation.
types/lib/utils/flush.d.ts
Outdated
/** | ||
* Adds a `Polymer.Debouncer` to a list of globally flushable tasks. | ||
*/ | ||
function enqueueDebouncer(debouncer: Polymer.Debouncer|null): void|null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can not be null
. That would throw an error later in flushDebouncers()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Updated @param
annotation.
types/lib/utils/gestures.d.ts
Outdated
/** | ||
* Adds an event listener to a node for the given gesture type. | ||
*/ | ||
function addListener(node: Node|null, evType: string, handler: Function|null): boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these (and in the later methods) can not be |null
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Updated @param
annotations.
types/lib/utils/import-href.d.ts
Outdated
* In the `onload` callback, the `import` property of the `link` | ||
* element will contain the imported document contents. | ||
*/ | ||
function importHref(href: string, onload?: Function|null, onerror?: Function|null, optAsync?: boolean): HTMLLinkElement|null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason this type is different than the one specified in legacy-element-mixin.d.ts
. Duplication FTW?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Made them the same.
types/lib/utils/settings.d.ts
Outdated
/** | ||
* Legacy settings. | ||
*/ | ||
namespace settings { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably add the declarations for the following:
namespace settings {
useNativeCSSProperties: boolean;
useNativeCustomElements: boolean;
useShadow: boolean;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the @namespace
annotation from settings
to Settings
so at least that's correct now. But actually there is no way in Analyzer to model this object and its interface. Going to punt on the full interface for now. The main way people use this is with a <script>
tag in their index.html
anyway, so it's unlikely it would need to be referenced from TypeScript.
* To modify these typings, edit the source file(s): | ||
* lib/utils/unresolved.html | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe do not generate the file if there were no types in it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently we mirror the HTML import graph to the reference import graph, so that complicates that a bit, since dependents need to know whether their dependency has anything. See also https://github.com/Polymer/gen-typescript-declarations/blob/master/src/gen-ts.ts#L114
PTAL. This PR is up to date with the latest changes to Polymer, Analyzer, and the type generator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is basically ready to merge, so it has my approval. Any nits can be fixed up later, otherwise this could go around forever. I'd like to see it go out with a 2.4.0 prerelease to get feedback on the types if possible.
I left a handful of observations on generated types that I think could be better (like a lot of methods that return any
but probably should return void
), but I think those can be incrementally improved either in the generator or Polymer itself. Just add issues.
One thing that would be nice is if we could run the generated types through the type checker to make sure they're at least well formed and all referenced built-in types are defined.
gulpfile.js
Outdated
const files = await genTs('.', config); | ||
for (const [filePath, contents] of files) { | ||
await fs.outputFile(path.join('types', filePath), contents); | ||
} | ||
}); | ||
|
||
gulp.task('update-version', () => { | ||
gulp.src('lib/utils/boot.html') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fyi, this task looks like it's missing a return statement. It should return the stream pipeline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't changed in this PR, but added a return.
types/extra-types.d.ts
Outdated
* Types from "externs/closure-types.js" | ||
*/ | ||
|
||
type Polymer_PropertyEffects = Polymer.PropertyEffects; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary? Add a comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer necessary. Fixed in Polymer/gen-typescript-declarations#47.
types/extra-types.d.ts
Outdated
|
||
/// <reference path="lib/mixins/property-effects.d.ts" /> | ||
|
||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be a /*
comment, since it's not a doc comment on the subsequent line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
types/extra-types.d.ts
Outdated
}; | ||
|
||
interface PolymerInit { | ||
is: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any comments to copy here? TODO maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added TODO. Nothing in the externs to copy so I'd be writing something new.
types/extra-types.d.ts
Outdated
} | ||
|
||
/** | ||
* Types from "lib/utils/async.html" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have types from regular source files? Is it cause we don't have interfaces in there? Might be worth a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some interfaces are defined directly in the source if they are only used in that one place. Not sure I need to comment that here? Did end up removing one case, since AsyncModule
turned out to be a re-definition of AsyncInterface
.
* | ||
* @returns Array of assigned nodes | ||
*/ | ||
getDistributedNodes(): Array<Node|null>|null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some places you have Foo[]
and here Array<Foo>
. TODO to parse Closure and convert?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is deliberate. If it's an array of a named type, we do Foo[]
, if it's anything more complicated we do Array<Foo | Bar | Baz>
, following the google typescript style guide.
* @param property Name of the property | ||
* @param value Value to set | ||
*/ | ||
_setProperty(property: string, value: any): any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should return void
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed by Tim in #4998
types/lib/utils/html-tag.d.ts
Outdated
* | ||
* @returns Constructed HTMLTemplateElement | ||
*/ | ||
function html(strings: ITemplateArray|null, ...values: any[]): HTMLTemplateElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null
shouldn't be allowed here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done (updated annotation in Polymer).
* | ||
* @returns The link element for the URL to be loaded. | ||
*/ | ||
function importHref(href: string, onload?: Function, onerror?: Function, optAsync?: boolean): HTMLLinkElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nice to have better types for the callbacks. Issue in Polymer core?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, would just need to update the @params
in import-href.html
. Punting for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funny, I filed an issue a ways back and it got comments recently: #4603
types/extra-types.d.ts
Outdated
/** | ||
* Closure type equivalence for tagged template literal function argument. | ||
*/ | ||
type ITemplateArray = TemplateStringsArray; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I didn't see this when I looked at Polymer.html
. Can't you just add this to the Closure -> TS type converter functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed via Polymer/gen-typescript-declarations#47.
I have a couple more comments:
I have opened #4998 to tighten almost all of the types to the correct value. This removes all |
I didn't want to pollute the global namespace with this type. I would have to somehow ensure it's only defined once when multiple repos' generated types are compiled together. |
Oops, yeah quite an omission. I've added static method support in Polymer/gen-typescript-declarations#46. Turned out representing static methods for mixins required significant refactoring of the way mixins are emitted. |
I've been testing manually, the current typings compile cleanly. It would be nice to automate it, maybe fail on Travis if it's not compiling. Maybe we should do the same for Closure compile too. Don't think I'll do that in this PR though. |
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
I would like to improve the warnings output by integrating with the very nice Analyzer warnings printer. For another time though.
These were from not supporting
This is from https://github.com/Polymer/polymer/blob/master/lib/utils/templatize.html#L61. Safe to ignore. |
I think this is ready to merge. All comments addressed. |
LGTM still |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM for now. There are still some incorrect : any
and incorrectly exposed private variables, but these are very few nits. I think it is better to merge this now and let end-users play with TypeScript support to get feedback, rather than perfect it right away. Nice work @aomarks !
Just a couple of things but they could be sorted in a future PR: Annotations:
If you want to get this merged, i don't mind doing a PR for these annotations. Misc:
Great work @aomarks, will be testing this out more through the week. |
Generated by https://github.com/Polymer/gen-typescript-declarations. Regenerate with
gulp generate-typescript
. Types are output to atypes/
directory.Fixes #4025