@@ -15,13 +15,19 @@ export type JsonValue =
1515
1616const F = ts . factory ;
1717
18+ export type ImportSpecifier = {
19+ name : string ;
20+ as ?: string ;
21+ isTypeOnly : boolean ;
22+ } ;
23+
1824/**
1925 * A helper class to build up a TypeScript document AST.
2026 */
2127export default class TSAstBuilder {
2228 _globalNames : Map < string , number > = new Map ( ) ;
2329 _imports : ts . Statement [ ] = [ ] ;
24- imports : Map < string , { name : string ; as ?: string } [ ] > = new Map ( ) ;
30+ imports : Map < string , ImportSpecifier [ ] > = new Map ( ) ;
2531 _helpers : ts . Statement [ ] = [ ] ;
2632 _statements : ts . Statement [ ] = [ ] ;
2733
@@ -170,21 +176,26 @@ export default class TSAstBuilder {
170176 ) ;
171177 }
172178
173- import ( from : string , names : { name : string ; as ?: string } [ ] ) {
179+ import ( from : string , names : ImportSpecifier [ ] ) {
174180 let moduleImports = this . imports . get ( from ) ;
175181 if ( moduleImports == null ) {
176182 moduleImports = [ ] ;
177183 this . imports . set ( from , moduleImports ) ;
178184 }
179- for ( const { name, as } of names ) {
185+ for ( const { name, as, isTypeOnly } of names ) {
180186 let seen = false ;
181187 for ( const imp of moduleImports ) {
182188 if ( imp . name === name && imp . as === as ) {
189+ // If a name is imported both as type only and as a value, it needs to
190+ // be imported as a value.
191+ if ( imp . isTypeOnly && ! isTypeOnly ) {
192+ imp . isTypeOnly = false ;
193+ }
183194 seen = true ;
184195 }
185196 }
186197 if ( ! seen ) {
187- moduleImports . push ( { name, as } ) ;
198+ moduleImports . push ( { name, as, isTypeOnly } ) ;
188199 }
189200 }
190201 }
@@ -203,6 +214,7 @@ export default class TSAstBuilder {
203214 tsModulePath : string ,
204215 exportName : string | null ,
205216 localName : string ,
217+ isTypeOnly : boolean ,
206218 ) : void {
207219 const abs = resolveRelativePath ( tsModulePath ) ;
208220 const relative = replaceExt (
@@ -213,7 +225,9 @@ export default class TSAstBuilder {
213225 if ( exportName == null ) {
214226 this . importDefault ( modulePath , localName ) ;
215227 } else {
216- this . import ( modulePath , [ { name : exportName , as : localName } ] ) ;
228+ this . import ( modulePath , [
229+ { name : exportName , as : localName , isTypeOnly } ,
230+ ] ) ;
217231 }
218232 }
219233
@@ -228,16 +242,21 @@ export default class TSAstBuilder {
228242 ) ;
229243
230244 for ( const [ from , names ] of this . imports ) {
245+ const allImportsAreTypeOnly = names . every ( ( name ) => name . isTypeOnly ) ;
231246 const namedImports = names . map ( ( name ) => {
247+ // If all the imports are type only, then we don't need to mark each
248+ // individual import as type only.
249+ const isTypeOnly = ! allImportsAreTypeOnly && name . isTypeOnly ;
250+
232251 if ( name . as && name . as !== name . name ) {
233252 return F . createImportSpecifier (
234- false ,
253+ isTypeOnly ,
235254 F . createIdentifier ( name . name ) ,
236255 F . createIdentifier ( name . as ) ,
237256 ) ;
238257 } else {
239258 return F . createImportSpecifier (
240- false ,
259+ isTypeOnly ,
241260 undefined ,
242261 F . createIdentifier ( name . name ) ,
243262 ) ;
@@ -247,7 +266,7 @@ export default class TSAstBuilder {
247266 F . createImportDeclaration (
248267 undefined ,
249268 F . createImportClause (
250- false ,
269+ allImportsAreTypeOnly ,
251270 undefined ,
252271 F . createNamedImports ( namedImports ) ,
253272 ) ,
0 commit comments