@@ -373,6 +373,17 @@ export interface CreateOptions {
373373 * For details, see https://nodejs.org/dist/latest-v18.x/docs/api/esm.html#customizing-esm-specifier-resolution-algorithm
374374 */
375375 experimentalSpecifierResolution ?: 'node' | 'explicit' ;
376+ /**
377+ * Allow using voluntary `.ts` file extension in import specifiers.
378+ *
379+ * Typically, in ESM projects, import specifiers must hanve an emit extension, `.js`, `.cjs`, or `.mjs`,
380+ * and we automatically map to the corresponding `.ts`, `.cts`, or `.mts` source file. This is the
381+ * recommended approach.
382+ *
383+ * However, if you really want to use `.ts` in import specifiers, and are aware that this may
384+ * break tooling, you can enable this flag.
385+ */
386+ experimentalTsImportSpecifiers ?: boolean ;
376387}
377388
378389export type ModuleTypes = Record < string , ModuleTypeOverride > ;
@@ -693,6 +704,11 @@ export function createFromPreloadedConfig(
693704 6059 , // "'rootDir' is expected to contain all source files."
694705 18002 , // "The 'files' list in config file is empty."
695706 18003 , // "No inputs were found in config file."
707+ ...( options . experimentalTsImportSpecifiers
708+ ? [
709+ 2691 , // "An import path cannot end with a '.ts' extension. Consider importing '<specifier without ext>' instead."
710+ ]
711+ : [ ] ) ,
696712 ...( options . ignoreDiagnostics || [ ] ) ,
697713 ] . map ( Number ) ,
698714 } ,
@@ -905,6 +921,8 @@ export function createFromPreloadedConfig(
905921 patterns : options . moduleTypes ,
906922 } ) ;
907923
924+ const extensions = getExtensions ( config , options , ts . version ) ;
925+
908926 // Use full language services when the fast option is disabled.
909927 if ( ! transpileOnly ) {
910928 const fileContents = new Map < string , string > ( ) ;
@@ -985,6 +1003,8 @@ export function createFromPreloadedConfig(
9851003 cwd,
9861004 config,
9871005 projectLocalResolveHelper,
1006+ options,
1007+ extensions,
9881008 } ) ;
9891009 serviceHost . resolveModuleNames = resolveModuleNames ;
9901010 serviceHost . getResolvedModuleWithFailedLookupLocationsFromCache =
@@ -1143,6 +1163,8 @@ export function createFromPreloadedConfig(
11431163 ts,
11441164 getCanonicalFileName,
11451165 projectLocalResolveHelper,
1166+ options,
1167+ extensions,
11461168 } ) ;
11471169 host . resolveModuleNames = resolveModuleNames ;
11481170 host . resolveTypeReferenceDirectives = resolveTypeReferenceDirectives ;
@@ -1448,7 +1470,6 @@ export function createFromPreloadedConfig(
14481470 let active = true ;
14491471 const enabled = ( enabled ?: boolean ) =>
14501472 enabled === undefined ? active : ( active = ! ! enabled ) ;
1451- const extensions = getExtensions ( config , options , ts . version ) ;
14521473 const ignored = ( fileName : string ) => {
14531474 if ( ! active ) return true ;
14541475 const ext = extname ( fileName ) ;
0 commit comments