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
{{ message }}
Repository navigation
Type definitions for 'Symbols as WeakMap keys' #52534
My compilation target is ESNext and my lib is the default.
Missing / Incorrect Definition
Symbols as WeakMap keys went to stage 4 at TC39 yesterday.
The types for WeakMap, WeakSet, WeakRef and FinalizationRegistry can be updated to reflect that symbol is now also allowed alongside the existing object constraint.
We discussed this in a design meeting recently. Even though the proposal makes an exception for registered symbols from Symbol.for, we don't want to take on the complexity to model that exception within the TypeScript type system. That means that our expectation is that we just expand the key constraint for WeakMap et al. to object | symbol, even if that means you can potentially write failing code like new WeakMap().set(Symbol.for("foo"), {}).
We have identified a complexity in regards to adding type support for the primitive symbol to WeakRef, WeakSet, and WeakMap. We also have a potential solution but wanted to get the TypeScript team’s opinion.
The problem originates from the change being to the constraint of a generic, which is not something interface merging supports. Illustrated at the example of WeakSet:
ES2015 :
interfaceWeakSet<Textendsobject>{
...
}
ES2023:
interfaceWeakSet<Textendsobject|symbol>{
...
}// Error! All declarations of 'WeakSet' must have identical type parameters.(2428)
The above addition in ES2023 would now lead to an invalid redefinition of the interface WeakSet as it does not use the same template parameter type for T.
Proposed Solution
Introduce a custom defined type to ES2015 based on an interface that can be augmented to include symbol alongside object. e.g.
ES2015:
/** * This type is used to 'store' the types that can be used with Weak{Map,Set,Ref} * es2022 **/interfaceAllowableWeakTypesStore{object: object;}typeAllowableWeakTypes=AllowableWeakTypesStore[keyofAllowableWeakTypesStore];interfaceWeakSet<Textends(AllowableWeakTypes&{})>{
...
}
ES2023:
interfaceAllowableWeakTypesStore{symbol: symbol;}
Alternative Solution (not favoured)
lib.es2023.d.ts would not directly reference lib.es2022.d.ts. Instead it would individually select the definitions from ES2015 up to ES2022 but avoid the files which define WeakSet, WeakMap, and WeakRef. This would allow ES2023 to define the type with a new constraint.
We discarded this since it requires duplicating the definitions for WeakSet, WeakMap, and WeakRef, and forks the library inheritance tree adding complexity and risk.
Any thoughts or alternative approaches are greatly appreciated! Thank you in advance!
The solution we use for ArrayBuffer | SharedArrayBuffer in typed array constructors is the same as your proposed solution with AllowableWeakTypesStore, so I would recommend that approach. I'd recommend a simpler name like WeakKeyTypes, though.
Reacted by Ashley Claymore and Leo Elmecker-Plakolm
Ron Buckton (@rbuckton) Somehow off topic, but I would like to see ArrayLike<T> | Iterable<T> using the same approach too. Currently many definitions in es5.d.ts are repeated in es2015.iterable.d.ts.
Activity
acutmore commentedon Feb 1, 2023
If 'contributions are welcome', there are developers at Bloomberg ready and standing by to contribute a PR.
acutmore commentedon Feb 9, 2023
Leo Elmecker-Plakolm (@leoelm) from Bloomberg (@bloomberg) has begun looking into the changes required for this.
rbuckton commentedon Feb 9, 2023
We discussed this in a design meeting recently. Even though the proposal makes an exception for registered symbols from
Symbol.for, we don't want to take on the complexity to model that exception within the TypeScript type system. That means that our expectation is that we just expand the key constraint forWeakMapet al. toobject | symbol, even if that means you can potentially write failing code likenew WeakMap().set(Symbol.for("foo"), {}).leoelm commentedon Feb 13, 2023
Hello all,
We have identified a complexity in regards to adding type support for the primitive symbol to
WeakRef,WeakSet, andWeakMap. We also have a potential solution but wanted to get the TypeScript team’s opinion.The problem originates from the change being to the constraint of a generic, which is not something interface merging supports. Illustrated at the example of
WeakSet:ES2015 :
ES2023:
The above addition in ES2023 would now lead to an invalid redefinition of the interface
WeakSetas it does not use the same template parameter type forT.Proposed Solution
Introduce a custom defined type to ES2015 based on an interface that can be augmented to include
symbolalongsideobject. e.g.ES2015:
ES2023:
Alternative Solution (not favoured)
lib.es2023.d.tswould not directly referencelib.es2022.d.ts. Instead it would individually select the definitions from ES2015 up to ES2022 but avoid the files which defineWeakSet,WeakMap, andWeakRef. This would allow ES2023 to define the type with a new constraint.We discarded this since it requires duplicating the definitions for
WeakSet,WeakMap, andWeakRef, and forks the library inheritance tree adding complexity and risk.Any thoughts or alternative approaches are greatly appreciated! Thank you in advance!
rbuckton commentedon Feb 13, 2023
The solution we use for
ArrayBuffer | SharedArrayBufferin typed array constructors is the same as your proposed solution withAllowableWeakTypesStore, so I would recommend that approach. I'd recommend a simpler name likeWeakKeyTypes, though.graphemecluster commentedon Feb 14, 2023
Ron Buckton (@rbuckton) Somehow off topic, but I would like to see
ArrayLike<T> | Iterable<T>using the same approach too. Currently many definitions ines5.d.tsare repeated ines2015.iterable.d.ts.rbuckton commentedon May 3, 2023
Ashley Claymore (@acutmore), Leo Elmecker-Plakolm (@leoelm): Is bloomberg#76 ready for a PR? It looks pretty much like what I would have written given my earlier suggestion.
acutmore commentedon May 4, 2023
Hi Ron Buckton (@rbuckton), thanks for taking a look at bloomberg#76. We've merged that now. I'll sync up with Leo Elmecker-Plakolm (@leoelm) and hopefully we'll get the PR to Microsoft open tomorrow.
[flow] Allow symbols to be used as WeakMap keys