-
Notifications
You must be signed in to change notification settings - Fork 78
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
docs(README.md): note that Flow's Class<T> works with type parameter but TS typeof T doesn't #62
Open
jedwards1211
wants to merge
1
commit into
niieani:master
Choose a base branch
from
jedwards1211:class-utility-type
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -291,13 +291,28 @@ const instance = new Test(); | |
type TestTypeFromInstance = Class<typeof instance>; | ||
``` | ||
|
||
This works with type parameters: | ||
```js | ||
function newInstance<T>(c: Class<T>) { | ||
... | ||
} | ||
``` | ||
|
||
### TypeScript | ||
|
||
```ts | ||
class Test {}; | ||
type TestType = typeof Test; | ||
``` | ||
|
||
This unfortunately doesn't work with type parameters: | ||
```ts | ||
// error: 'T' only refers to a type, but is being used as a value here.(2693) | ||
function newInstance<T>(c: typeof T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But you can: declare function newInstance<T>(c: new (..._: any) => T): T;
var x = newInstance(class X { y = 1; });
x.y = 2 |
||
... | ||
} | ||
``` | ||
|
||
## Keys/Props Of Type | ||
|
||
### Flow | ||
|
@@ -405,7 +420,7 @@ These are functions that return a boolean, performing some logic to assert that | |
|
||
The implementations differ between Flow and TypeScript: | ||
|
||
In TypeScript, it ensures the mapping between: `true` and `value is T`, versus in the case of Flow, it ensures the value is "checked" against the logic within the body of the function (i.e. things like `typeof`, `instanceof`, `value === undefined`). | ||
In TypeScript, it ensures the mapping between: `true` and `value is T`, versus in the case of Flow, it ensures the value is "checked" against the logic within the body of the function (i.e. things like `typeof`, `instanceof`, `value === undefined`). | ||
|
||
This means you cannot tell Flow that the tested parameter is of an arbitrary type, which closes the door to complex cases, e.g.: | ||
- reusing logic from a different function | ||
|
@@ -654,7 +669,7 @@ type C = Omit<A, B>; | |
// C is { b: number } | ||
``` | ||
|
||
However, Flow implementation is stricter in this case, as B have a property that A does not have, it would rise an error. In Typescript, however, they would be ignored. | ||
However, Flow implementation is stricter in this case, as B have a property that A does not have, it would rise an error. In Typescript, however, they would be ignored. | ||
|
||
# Same syntax | ||
|
||
|
@@ -683,8 +698,8 @@ This is supported by Flow. And we list out the different syntaxes here: [Try Flo | |
|
||
```js | ||
type F = { | ||
(): string, | ||
[[call]]: (number) => string, | ||
(): string, | ||
[[call]]: (number) => string, | ||
[[call]](string): string | ||
} | ||
|
||
|
@@ -719,7 +734,7 @@ Reference: | |
|
||
- [Callable Objects](https://flow.org/en/docs/types/functions/#callable-objects-) | ||
- [immer.js](https://github.com/immerjs/immer/blob/master/src/immer.js.flow) uses it to overload the `produce` (default export) function which has multiple call signatures | ||
- [Styled Components](https://github.com/flow-typed/flow-typed/blob/master/definitions/npm/styled-components_v4.x.x/flow_v0.75.x-/styled-components_v4.x.x.js#L242) uses it to separate cases of being called on a string and wrapping a component | ||
- [Styled Components](https://github.com/flow-typed/flow-typed/blob/master/definitions/npm/styled-components_v4.x.x/flow_v0.75.x-/styled-components_v4.x.x.js#L242) uses it to separate cases of being called on a string and wrapping a component | ||
- [Reselect Library Definition](https://github.com/flow-typed/flow-typed/blob/master/definitions/npm/re-reselect_v2.x.x/flow_v0.67.1-/re-reselect_v2.x.x.js) contains massive chunks of overloaded call properties | ||
|
||
### TypeScript | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
But you can:
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.
Okay, I could include that, but I bet it has some limitations like not having type information about the static members of the class, right? I'm 95% sure
Class<T>
in Flow includes the static member typesThere 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.
Well, It's not clear how you want to use it. Flow has some limitations too, it's not like that in all scenarios you just get the
static
s part with this annotation. It's still a generic, (but the last Flow version I've used is 0.85). But, TS is anyway not the best in inference ofstatic
properties and even when it's suppose to have the information.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 case works in Flow at least:
I'm just saying if we include a note about
new (..._: any) => T
types, we should mention that it definitely doesn't capture static member types, but thatClass<T>
can.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.
In the moment you add
:
in the generics it's become pointless. It's not a "real life usage". Because I would probably write it as:I think that this demo is quite pointless. You better right about the fact that TS is really weak about static fields and you cannot get them through
constructor
, aka:But
Class<T>
utility isn't that different thantypeof
. The fact TS doesn't recognizestatic
fields is the real different.If you wouldn't use
:
in the demo, only if a function isn't exported it might work and than you wouldn't need any type annotations (this is where Flow shines).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.
sequelize
definitions are over-typed (By the way I guess in TS it would done very differently). I said giving overtype examples for non-real life senecrious isn't good a thing.The main point, I think
Class<T>
vstypeof T
isn't a good example, because it's misleading and unclear to the point, But showing TS can't handlestatic
properties or "prototype chain" is way more relevant while Flow does itThere 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.
Okay, I'm just having trouble understanding why you're against my proposed changes. Would you be in agreement with something like
I should research whether
typeof T
captures static class member type information either though (though if it doesn't already, I would expecttypeof T
to capture static members in the future, whereas I assumenew (..._: any) => T
will never capture static members.)Or can you propose how you would describe the differences in typing classes, including typing static members?
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.
Okay for reference with latest typescript playground:
So it's not correct to say that TS can't handle static properties; it certainly does with
typeof
, it just can't do so on a generic type, and this is a concrete difference from Flow I think it would benefit people to know.So I think anything we document about differences in class typing must discuss both
typeof T
andnew (..._: any) => T
, the differences between each, and the fact that Flow can capture the class static member types even when theT
inClass<T>
is a type parameter.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.
TS don't deal
static
s as part of prototype object well.typeof SomeClass
will work as much astypeof anyInstanceObject
. ButanyInstanceObject.prototype.constructor.*
won't work in TS, Only in Flow.I didn't say I'm against, I'm not a maintainer of this project and don't decide what goes in or not.
I think it's misleading to present it as "
Class<T>
vstypeof T
". It's not the important part for my opinion and quite misleading. Talking about limitation to extractstatic
properties from TS comparing to Flow is way more important and accurateThere 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's very important for people migrating from Flow to TS to learn what to use instead of
Class<T>
. They need to know that they won't be able to fully replicateClass<T>
in some situations.I get that
typeof T
is not the only answer, my TS section needs to mention bothtypeof T
andnew (..._: any) => T
to provide a complete answer. You may only usenew (..._: any) => T
but it's not necessarily sufficient for everyone's purposes.