Skip to content

A compiler option to enforce file extensions.Β #42813

@trusktr

Description

@trusktr

Suggestion

A compiler option like requireExtensions would be great.

πŸ” Search Terms

typescript compiler require import extensions

βœ… Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

A compiler option like requireExtensions would enforce .js extensions to make modules ESM-compatible without additional tooling, imports maps, or package.json exports fields.

πŸ“ƒ Motivating Example

ESM ecosystem (Node, Webpack 5+, etc) follows the Node ESM standards. Tools like Webpack will throw a compile error on non-confoming ES Modules (when they don't conform to Node ESM spec), and Webpack full understands the package.json exports field when resolving modules for example.

πŸ’» Use Cases

This would help to enforce writing code that is more likely to work well in strict Node ESM environments.

In Webpack 5, importing TypeScript output code that does no include extensions (although TS gives no error) results in a compile error for packages with "type": "module" in their package.json during Webpack's resolution (it behaves identical to Node ESM).


With requireExtensions set to false, the following code would be valid:

import {foo} from './foo'
import {bar} from 'some-lib'
import {baz} from 'some-lib/baz'
import {lorem} from '@org/some-lib/lorem'

With requireExtensions set to true, the following code would be valid only if moduleResolution is also set to "node":

import {foo} from './foo.js'
import {bar} from 'some-lib'
import {baz} from 'some-lib/baz.js'
import {lorem} from '@org/some-lib/lorem.js'

otherwise with a different value of moduleResolution it would probably need to be

import {foo} from './foo.js'
import {bar} from 'some-lib.js'
import {baz} from 'some-lib/baz.js'
import {lorem} from '@org/some-lib/lorem.js'

Metadata

Metadata

Assignees

No one assigned

    Labels

    In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions