-
Notifications
You must be signed in to change notification settings - Fork 362
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 declaration files #1578
Conversation
8a43ce1
to
1fe5308
Compare
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.
LGTM - would be awesome to get typedefs out of the box. Especially for loopback
core as well for things like User
, Role
and app
.
I did notice Model
is missing a few of the static
methods like remoteMethod
, nestRemoting
and getApp
.
export interface ScopedMethods<T extends ModelBase = ModelBase> { | ||
build(data: ModelData<T>): T; | ||
|
||
create( |
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.
What about the overloads for all of these methods? E.g. you can technically skip options and just provide the callback:
create(data: ModelData<T>, callback: Callback<T>): PromiseOrVoid<T>;
my preference would be to explicitly list these so that if you don't pass in a callback you know you're getting a promise:
create(data: ModelData<T>, options?: Options): Promise<T>;
create(data: ModelData<T>, callback: Callback<T>): void;
create(data: ModelData<T>, options: Options, callback: Callback<T>): void;
Also, I believe create
also supports arrays of data for bulk creates:
create(data: ModelData<T> | ModelData<T>[]): Promise<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.
@zbarbuto Thank you for chiming in. It's a good idea to use overloaded method signatures. Let's do it incrementally. I would like to use the type information for LoopBack 4 soon.
For loopback
module, I think there is already a community module - @types/loopback
. Do you want to check out?
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.
Yes have used this in the past - it does have some issues. Was only mentioning in case it was on the cards to eventually have typedefs out of the box in loopback
as well.
Understood re: changing incrementally.
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.
@zbarbuto I don't think I include Model
in the declaration files. Please note that ModelBase
is different from Model
:
- ModelBase: a base class in
loopback-datasource-juggler
as the common root of all models - Model: a class in
loopback
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.
Great start!
I did not review the actual types in details, it's too difficult to verify their correctness manually. Can we mark TypeScript support as experimental to allow us to make backwards-incompatible fixes in semver-minor versions?
I have few high-level comments and topics to discuss, see below.
.prettierrc
Outdated
@@ -0,0 +1,6 @@ | |||
{ | |||
"bracketSpacing": false, | |||
"singleQuote": true, |
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.
Let's not mix adding Prettier with typings. Could you please open a new PR adding Prettier to our workflow (including npm test
executed by CI)? Alternatively, keep these prettier-related files local only to help your IDE, don't commit them to git.
@@ -0,0 +1,18 @@ | |||
{ | |||
"$schema": "http://json.schemastore.org/tsconfig", | |||
"compilerOptions": { |
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 am confused why do we need a tsconfig file, when this project does not contain any TypeScript sources to compile, only .d.ts
files. Could you please clarify?
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 presence of tsconfig.json
file allows VsCode to validate the syntax of .d.ts
files.
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.
Cool!
I think we should have a build step to run that validations, otherwise our .d.ts
files can quickly become invalid. I consider this as a must have for this pull request.
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 see you have added npm run tsc
, we are good here 👍
* | ||
* Note that juggler uses Bluebird, not the native Promise. | ||
*/ | ||
export type PromiseOrVoid<T = any> = PromiseLike<T> | 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.
I don't see any import or definition of PromiseLike<T>
, perhaps an oversight on your side?
I think we need to introduce some kind of a smoke test (as part of this pull request!) to at least verify that type definitions can be parsed & loaded by tsc
.
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.
PromiseLike
is a built-in type from lib.es5.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.
I added npm run tsc
to validate *.d.ts
files.
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.
Great!
* 3. new DataSource(connectorModule, settings). For example: | ||
* - new DataSource(connectorModule, {name: 'myDataSource}) | ||
* - new DataSource(connectorModule) | ||
*/ |
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.
Is it a good idea to duplicate the jsdoc comments in typing files? I am concerned that the content in .d.ts
files will quickly get out of sync with the original comments in .js
files.
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.
When the package is used by other modules such as @loopback/repository
, VSCode uses the tsdocs from .d.ts
file, IIUC.
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 see, that makes sense.
It would be great to find a way how to automatically sync these jsdoc/tsdoc comments, but that's out of scope of this pull request.
types/model.d.ts
Outdated
import {EventEmitter} from 'events'; | ||
|
||
// tslint:disable:no-any | ||
// tslint:disable:max-line-length |
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.
AFAICT, we don't have tslint
integration in juggler, therefore we should not need any tslint
overrides.
types/persisted-model.d.ts
Outdated
count: number; | ||
} | ||
|
||
export declare class PersistedModel extends ModelBase { |
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.
Technically speaking, there is no such thing as a PersistedModel
at juggler level. We have ModelBase
and DataAccessObject
mixin that's added to ModelBase
when a model is attached to a datasource using the default DAO implementation. Similarly, we have KeyValueAccessObject
mixin that provides API for models connected to key-value stores.
The class PersistedModel
is implemented in loopback
, as a thin wrapper providing default DAO methods which throw a helpful message when the model was not attached to a datasource yet.
In the light of that, I feel the currently proposed typedefs are subtly incorrect and I would prefer if we could find a way how to make .d.ts
files closer to the actual juggler API and behavior.
Thoughts?
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'll check
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.
LB3 uses mixins at runtime to build model classes. Even though the PersistedModel
is physically from loopback
module, we do have the assumption of PersistedModel
class in many cases in loopback-datasource-juggler
.
It's hard to describe such contracts in other forms such as interfaces to allow both static and prototype methods/properties.
a11a3fb
to
ab3412d
Compare
I'll see. This is an interesting problem, I may give it a try myself. For now, I am ok with a suboptimal solution that works right now. |
@@ -13,5 +13,5 @@ npm-debug.log | |||
.project | |||
test/memory.json | |||
.nyc_output | |||
|
|||
dist |
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.
Please add dist
to .npmignore too.
@@ -0,0 +1,18 @@ | |||
{ | |||
"$schema": "http://json.schemastore.org/tsconfig", | |||
"compilerOptions": { |
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 see you have added npm run tsc
, we are good here 👍
Few more comments (see above), I think this is almost ready to be landed. My expectation is that we will be fixing any bugs as we discover them from real-world usage, thus this initial typings can be landed quickly. I feel it's really important to clearly set the expectations about the stability of the TypeScript type definitions. Could you please add a bold comment to |
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.
Awesome stuff @raymondfeng. I just looked at datasource.d.ts
and was wondering why we have some missing methods compared to https://apidocs.strongloop.com/loopback-datasource-juggler/#datasource? Perhaps it's because we'd like to add them incrementally?
types/datasource.d.ts
Outdated
connected?: boolean; | ||
connecting?: boolean; | ||
|
||
connector?: 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.
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.
d0f08c4
to
ebcf6de
Compare
ebcf6de
to
77a2c9a
Compare
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.
LGTM 👍 , although I haven't looked through all the details. I'm good with the plan to modify incrementally.
Agree with @b-admike - LGTM for a first-pass |
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.
Description
This PR adds basic TypeScript declarations for juggler related types to be referenced in LoopBack 4.
Related issues
Checklist
guide