@@ -25,27 +25,81 @@ namespace ts {
2525 }
2626
2727 /** ES6 Map interface, only read methods included. */
28- export interface ReadonlyMap < T > {
29- get ( key : string ) : T | undefined ;
30- has ( key : string ) : boolean ;
31- forEach ( action : ( value : T , key : string ) => void ) : void ;
28+ export interface ReadonlyESMap < K , V > {
29+ get ( key : K ) : V | undefined ;
30+ has ( key : K ) : boolean ;
31+ forEach ( action : ( value : V , key : K ) => void ) : void ;
3232 readonly size : number ;
33- keys ( ) : Iterator < string > ;
34- values ( ) : Iterator < T > ;
35- entries ( ) : Iterator < [ string , T ] > ;
33+ keys ( ) : Iterator < K > ;
34+ values ( ) : Iterator < V > ;
35+ entries ( ) : Iterator < [ K , V ] > ;
3636 }
3737
3838 /** ES6 Map interface. */
39- export interface Map < T > extends ReadonlyMap < T > {
40- set ( key : string , value : T ) : this;
41- delete ( key : string ) : boolean ;
39+ export interface ESMap < K , V > extends ReadonlyESMap < K , V > {
40+ set ( key : K , value : V ) : this;
41+ delete ( key : K ) : boolean ;
4242 clear ( ) : void ;
4343 }
4444
45+ /** ES6 Map interface, only read methods included. */
46+ export interface ReadonlyMap < T > extends ReadonlyESMap < string , T > {
47+ }
48+
49+ /** ES6 Map interface. */
50+ export interface Map < T > extends ESMap < string , T > , ReadonlyMap < T > {
51+ }
52+
4553 /* @internal */
4654 export interface MapConstructor {
4755 // eslint-disable-next-line @typescript-eslint/prefer-function-type
48- new < T > ( ) : Map < T > ;
56+ new < K , V > ( ) : ESMap < K , V > ;
57+ }
58+
59+ export interface ReadonlySet < T > {
60+ readonly size : number ;
61+ has ( value : T ) : boolean ;
62+ forEach ( action : ( value : T , key : T ) => void ) : void ;
63+ keys ( ) : Iterator < T > ;
64+ values ( ) : Iterator < T > ;
65+ entries ( ) : Iterator < [ T , T ] > ;
66+ }
67+
68+ export interface Set < T > extends ReadonlySet < T > {
69+ add ( value : T ) : this;
70+ delete ( value : T ) : boolean ;
71+ clear ( ) : void ;
72+ }
73+
74+ /* @internal */
75+ export interface SetConstructor {
76+ // eslint-disable-next-line @typescript-eslint/prefer-function-type
77+ new < T > ( ) : Set < T > ;
78+ }
79+
80+ export interface WeakMap < K extends object , V > {
81+ get ( key : K ) : V | undefined ;
82+ has ( key : K ) : boolean ;
83+ set ( key : K , value : V ) : this;
84+ delete ( key : K ) : boolean ;
85+ }
86+
87+ /* @internal */
88+ export interface WeakMapConstructor {
89+ // eslint-disable-next-line @typescript-eslint/prefer-function-type
90+ new < K extends object , V > ( ) : WeakMap < K , V > ;
91+ }
92+
93+ export interface WeakSet < T extends object > {
94+ has ( key : T ) : boolean ;
95+ add ( key : T ) : this;
96+ delete ( key : T ) : boolean ;
97+ }
98+
99+ /* @internal */
100+ export interface WeakSetConstructor {
101+ // eslint-disable-next-line @typescript-eslint/prefer-function-type
102+ new < T extends object > ( ) : WeakSet < T > ;
49103 }
50104
51105 /** ES6 Iterator type. */
@@ -75,8 +129,12 @@ namespace ts {
75129/* @internal */
76130namespace ts {
77131 // Natives
78- // NOTE: This must be declared in a separate block from the one below so that we don't collide with the exported definition of `Map`.
79- declare const Map : ( new < T > ( ) => Map < T > ) | undefined ;
132+ // NOTE: This must be declared in a separate block from the one below so that we don't collide with the exported definitions of `Map` and `Set`.
133+
134+ declare const Map : MapConstructor | undefined ;
135+ declare const Set : SetConstructor | undefined ;
136+ declare const WeakMap : WeakMapConstructor | undefined ;
137+ declare const WeakSet : WeakSetConstructor | undefined ;
80138
81139 /**
82140 * Returns the native Map implementation if it is available and compatible (i.e. supports iteration).
@@ -86,28 +144,79 @@ namespace ts {
86144 // eslint-disable-next-line no-in-operator
87145 return typeof Map !== "undefined" && "entries" in Map . prototype ? Map : undefined ;
88146 }
147+
148+ /**
149+ * Returns the native Set implementation if it is available and compatible (i.e. supports iteration).
150+ */
151+ export function tryGetNativeSet ( ) : SetConstructor | undefined {
152+ // Internet Explorer's Set doesn't support iteration, so don't use it.
153+ // eslint-disable-next-line no-in-operator
154+ return typeof Set !== "undefined" && "entries" in Set . prototype ? Set : undefined ;
155+ }
156+
157+ /**
158+ * Returns the native WeakMap implementation if it is available.
159+ */
160+ export function tryGetNativeWeakMap ( ) : WeakMapConstructor | undefined {
161+ return typeof WeakMap !== "undefined" ? WeakMap : undefined ;
162+ }
163+
164+ /**
165+ * Returns the native WeakSet implementation if it is available.
166+ */
167+ export function tryGetNativeWeakSet ( ) : WeakSetConstructor | undefined {
168+ return typeof WeakSet !== "undefined" ? WeakSet : undefined ;
169+ }
89170}
90171
91172/* @internal */
92173namespace ts {
93174 export const emptyArray : never [ ] = [ ] as never [ ] ;
94175
95176 export const Map : MapConstructor = tryGetNativeMap ( ) || ( ( ) => {
96- // NOTE: createMapShim will be defined for typescriptServices.js but not for tsc.js, so we must test for it.
177+ // NOTE: ts. createMapShim will be defined for typescriptServices.js but not for tsc.js, so we must test for it.
97178 if ( typeof createMapShim === "function" ) {
98179 return createMapShim ( ) ;
99180 }
100181 throw new Error ( "TypeScript requires an environment that provides a compatible native Map implementation." ) ;
101182 } ) ( ) ;
102183
184+ export const Set : SetConstructor = tryGetNativeSet ( ) || ( ( ) => {
185+ // NOTE: ts.createSetShim will be defined for typescriptServices.js but not for tsc.js, so we must test for it.
186+ if ( typeof createSetShim === "function" ) {
187+ return createSetShim ( ) ;
188+ }
189+ throw new Error ( "TypeScript requires an environment that provides a compatible native Set implementation." ) ;
190+ } ) ( ) ;
191+
192+ export const WeakMap : WeakMapConstructor = tryGetNativeWeakMap ( ) || ( ( ) => {
193+ // NOTE: ts.createWeakMapShim will be defined for typescriptServices.js but not for tsc.js, so we must test for it.
194+ if ( typeof createWeakMapShim === "function" ) {
195+ return createWeakMapShim ( ) ;
196+ }
197+ throw new Error ( "TypeScript requires an environment that provides a compatible native WeakMap implementation." ) ;
198+ } ) ( ) ;
199+
200+ export const WeakSet : WeakSetConstructor = tryGetNativeWeakSet ( ) || ( ( ) => {
201+ // NOTE: ts.createWeakSetShim will be defined for typescriptServices.js but not for tsc.js, so we must test for it.
202+ if ( typeof createWeakSetShim === "function" ) {
203+ return createWeakSetShim ( ) ;
204+ }
205+ throw new Error ( "TypeScript requires an environment that provides a compatible native WeakSet implementation." ) ;
206+ } ) ( ) ;
207+
103208 /** Create a new map. */
104- export function createMap < T > ( ) : Map < T > {
105- return new Map < T > ( ) ;
209+ export function createMap < T > ( ) : Map < T > ;
210+ export function createMap < K , V > ( ) : ESMap < K , V > ;
211+ export function createMap < K , V > ( ) : ESMap < K , V > {
212+ return new Map < K , V > ( ) ;
106213 }
107214
108215 /** Create a new map from an array of entries. */
109- export function createMapFromEntries < T > ( entries : [ string , T ] [ ] ) : Map < T > {
110- const map = createMap < T > ( ) ;
216+ export function createMapFromEntries < T > ( entries : readonly [ string , T ] [ ] ) : Map < T > ;
217+ export function createMapFromEntries < K , V > ( entries : readonly [ K , V ] [ ] ) : ESMap < K , V > ;
218+ export function createMapFromEntries < K , V > ( entries : readonly [ K , V ] [ ] ) : ESMap < K , V > {
219+ const map = createMap < K , V > ( ) ;
111220 for ( const [ key , value ] of entries ) {
112221 map . set ( key , value ) ;
113222 }
@@ -116,7 +225,7 @@ namespace ts {
116225
117226 /** Create a new map from a template object is provided, the map will copy entries from it. */
118227 export function createMapFromTemplate < T > ( template : MapLike < T > ) : Map < T > {
119- const map : Map < T > = new Map < T > ( ) ;
228+ const map : Map < T > = new Map < string , T > ( ) ;
120229
121230 // Copies keys/values from template. Note that for..in will not throw if
122231 // template is undefined, and instead will just exit the loop.
@@ -129,6 +238,18 @@ namespace ts {
129238 return map ;
130239 }
131240
241+ export function createSet < T > ( ) : Set < T > {
242+ return new Set < T > ( ) ;
243+ }
244+
245+ export function createSetFromValues < T > ( values : readonly T [ ] ) : Set < T > {
246+ const set = createSet < T > ( ) ;
247+ for ( const value of values ) {
248+ set . add ( value ) ;
249+ }
250+ return set ;
251+ }
252+
132253 export function length ( array : readonly any [ ] | undefined ) : number {
133254 return array ? array . length : 0 ;
134255 }
0 commit comments