- Notifications
You must be signed in to change notification settings - Fork 13.2k
Keysof type operator#10425
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
Keysof type operator #10425
Uh oh!
There was an error while loading. Please reload this page.
Conversation
01b0744 to b156f71Comparealitaheri commented Aug 20, 2016
Also probably solves #7722. How would classes and namespaces work with this? ( if they should in the first place 😅 ) and how about index signatures? interfaceA{ foo: string;[property: string]: any;}what will be |
weswigham commented Aug 20, 2016
@alitaheri: |
| if (!type.resolvedBaseUnion){ | ||
| // Skip any essymbol members and remember to unescape the identifier before making a type from it | ||
| const memberTypes = map(filter(getPropertiesOfType(type.baseType), | ||
| symbol => !startsWith(symbol.name, "__@")), |
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 you split this into intermediate variables?
wclr commented Sep 1, 2016
When this going to landed? |
DanielRosenwasser commented Sep 1, 2016 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@whitecolor We need to discuss this at a design meeting. There are small details that can make all the difference (such as what to do with index signatures). |
wclr commented Sep 1, 2016
@DanielRosenwasser it would be cool if another part for #1295 would be implemented soon |
aluanhaddad commented Oct 1, 2016 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
I think this is a big step forward for the type system. The question I have, and sorry if this has already been answered, is this: What is the enumeration algorithm used?
On the one hand, it could be very surprising to not get the property keys of super class properties, especially as subclassing becomes more and more fashionable. On the other, it would be equally surprising if it behaved differently from Personally, I would prefer it to only return enumerable own properties, but I almost never create class hierarchies in TypeScript. |
DanielRosenwasser commented Oct 1, 2016
@aluanhaddad Problem is that enumerable own properties aren't encoded in the type system and there's not really a straightforward way we've thought of to add it. @sandersn ran into similar issues with the object rest & spread operators. |
aluanhaddad commented Oct 1, 2016 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@DanielRosenwasser thank you for clarifying. It makes a lot of sense that the language does not track own properties because statically modelling the flexibility of JavaScript's composition mechanisms would seem to preclude doing so. Perhaps if this operator walks the prototype chain a different name would be appropriate.
|
remojansen commented Oct 24, 2016
I created #11813 because I was not aware of this. I have closed it but it can still be used as a real world use case for the need of this operator. |
wycats commented Oct 25, 2016
@aluanhaddad I can understand why you expect That said, I'd find it unfortunate if this very useful operator was restricted to enumerable-own properties. Here's an example scenario I ran into today that got me thinking about this feature again: creating a hard-fail version of the index-for-friendly-access trick: classX{constructor(privatename: string){}}letx=newX("Godfrey");x['name']// type checks, "Godfrey", type is string, as expectedx['nmae']// type checks, undefined, type is any, unexpectedIn other words, this trick conflates the elimination of privacy checks with a willingness to accept successful type-checking and We could use the classX{constructor(privatename: string){}}letx=newX("Godfrey");x['name']// type checks, value is "Godfrey", type is string, as expectedx['nmae']// type checks, value is undefined, type is any, unexpectedfunctionget<T,KextendskeysofT>(obj: T,key: K){returnobj[key];}letx=newX("Godfrey");get(x,'name')// type checks, "Godfrey", type is string (?), as expectedget(x,'nmae')// fails to type checkWhether this works or not depends on whether Regardless of those details, this illustrates that there may be valid use-cases for My own perspective is that This might also argue for a few flavors of Finally, I also wonder whether not encoding enumerable/own in the type system will be practical in the long-term, especially considering the soon-to-be-included object-spread ( |
aluanhaddad commented Oct 30, 2016
@wycats I think you're points about overall usefulness outweigh my arguments about consistency with existing features. While I don't use classes particularly often I do find the object-spread example very compelling. In light of that feature, requiring ownness would kill a lot of the usefulness even in scenarios involving simple object literals. Also if manifest mixin support is ever added to ECMAScript, restricting it to enumerable own properties would also be very unfortunate. I am convinced. |
ahejlsberg commented Nov 2, 2016
Closing as this has been superseded by #11929. |
Fixes half of #1295. (Honestly, that issue is like proposals for three separate but interoperating features) The remaining parts of #1295 are what I call a "type access expression" - a mirror of element access expressions, but for types (quite literally the same logic) - and altering index resolution logic to, rather than using unions to check for index signature compatibility, be able to use a union of string literals to create a union of the types of those members.
The part that this PR addresses is an operator for finding all of the keys of an arbitrary type. This PR adds a new "type operator" (akin to
typeof) -keysof. Used like so:A parameter or return type being a
keysoftype causes it to be contextually types as a string literal if need be. Akeysoftype resolves to a union of the string literal types of the keys of the given type when it is actually resolved (which it is resolved to for relationship checking). It isStringLike, and as such it has the apparent type of a string. It is effectively sugar for writing out the union type of all the keys of an object by hand, except it is also able to be generically instantiated.cc @DanielRosenwasser