You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Idea: start with just new index signature types (i.e. symbol, template string), and come back to this problem.
With a mapped type like Record, we have a lot of subtlety on how to construct an object type:
string, number become index signatures
Individual unique keys like "hello" and "world" each get their own properties like hello and world.
Generics - we don't create keys for them.
We have freedom to grow in the space of creating a property with a union type.
There's definitely some "strangeness".
declareconstq: "hello"|"world";interfaceA{["hello"|"world"]: number;// this could create several optional properties}
declareconstq: "hello"|"world";interfaceA{[q]: number;// this could create several optional properties OR several known properties}
declareconstq: "hello"|"world";// this could create several optional properties// OR a union of several object typesletobj={[q]: 123;}interfaceObjType{[typeofq]: number}
You'd hope that obj is compatible with ObjType.
"Can I have arbitrary index signatures?" = one of several ideas, not all which are consistent.
Patterns in index signatures
Now we can cover that with template literal index signatures.
Mapped types can preserve these consistently.
A thing that I can only index with an enum type.
You can do Record<SomeEnum, SomeType>, but we erase the "enuminess" - just create keys based on the underlying runtime values.
Not strict, but kind of weird to differentiate these - if E.A is equal to 1, then why does it get its own key in a union? Weird.
enumE{A=0,B=1}typeFoo=Record<E,number>;declareletx: Foo;x[E.A]// okay - yay!x[0]// want this to not be okay - neigh!
A "static" version of Object.prototype.hasOwnProperty.
Object.create(null).hasOwnProperty ❌
People usually instead write Object.prototype.hasOwnProperty.call(...)
[[Bike-shedding on how it should look in lib.d.ts]]
hasOwn should not make your types worse.
Issues which revisits behavior of last topic - always fall back to an index signature if a property is not found.
Need for a "rest" index signature in some ways.
What about the differences between in and hasOwn?
They're there, but probably not worth special-casing the control flow behavior.
Writing as a type guard has too many nuances, subtleties.
We would like to be able to have a type signature annotation to convey what hasOwn does, but there's complexity in that. Leaning towards a syntactic construct.
People are not always polyfilling on globals due to frozen realms etc.
hasKey<T, K extends any>(x: T, k: K): K in T?
Revisit.
The text was updated successfully, but these errors were encountered:
Generalized Index Signatures
#26797
A couple of asks:
symbol
indexersWe don't want to have arbitrary indexers - don't like the idea of generics that get instantiated.
Also, we want to preserve "round-trippability"
What's the keyof?
Record
?Are these properties? Do you preserve the index signature?
How does this compare with computed properties?
Could imagine that this would be valid
desugars to
and
desugars to
Use-case: string enum index signature
Idea: start with just new index signature types (i.e. symbol, template string), and come back to this problem.
With a mapped type like
Record
, we have a lot of subtlety on how to construct an object type:string
,number
become index signatures"hello"
and"world"
each get their own properties likehello
andworld
.We have freedom to grow in the space of creating a property with a union type.
obj
is compatible withObjType
."Can I have arbitrary index signatures?" = one of several ideas, not all which are consistent.
Patterns in index signatures
A thing that I can only index with an enum type.
Record<SomeEnum, SomeType>
, but we erase the "enuminess" - just create keys based on the underlying runtime values.E.A
is equal to1
, then why does it get its own key in a union? Weird.Object.hasOwn
#44253
Object.prototype.hasOwnProperty
.Object.create(null).hasOwnProperty
❌Object.prototype.hasOwnProperty.call(...)
lib.d.ts
]]hasOwn
should not make your types worse.in
andhasOwn
?hasOwn
does, but there's complexity in that. Leaning towards a syntactic construct.hasKey<T, K extends any>(x: T, k: K): K in T
?The text was updated successfully, but these errors were encountered: