Skip to content

Add syntax hint to allow reexports of types in isolatedModules mode #34750

Closed
@BPScott

Description

@BPScott

Search Terms

isolatedModules, type export, type re-export, babel

Context

In --isolatedModules mode you get an error when reexporting types, the reason why this breaks is documented in the new handbook. In the following example lines 2 and 5 both raise give "Cannot re-export a type when the '--isolatedModules' flag is provided." warnings.

import { SomeType } from "someModule";
export { SomeType };
let x: SomeType | undefined;

export { SomeOtherType } from "someModule";

This leaves programme authors who wish to compile using a per-file compiler with some choices:

Use export * from "someModule", which will deal with all exports, but won't work if you need to cherry pick exports. It's usually possibly to rearchitect your folder structure to work around this but not always.

Or use a temporary renaming:

import { SomeType as SomeType1, SomeOtherType as SomeOtherType1 } from "someModule";
export type SomeType = SomeType1;
let x: SomeType | undefined;

export type SomeOtherType = SomeOtherType1;

Prior to #31231 (to be released in TS 3.7) authors could export a type that matches the same name as an import, but that loophole has been closed:

import { SomeType, SomeOtherType } from "someModule";
export type SomeType = SomeType;
let x: SomeType | undefined;

export type SomeOtherType = SomeOtherType;

Authors should not have to go through such renaming dances in order to get type reexports working in isolatedModules mode, instead it should be possible to hint that an import / reexport is of a type.

Suggestion

Add some kind of syntax hint to imports and reexports that denote that a particular identifier is a type and thus can be elided when compiling in isolatedModules mode.

Here I'm proposing the strawman of a type keyword before the ImportSpecifier / ExportSpecifier, as suggested by @Jessidhia in #31231 (comment). This is the same syntax Flow uses though I must admit I'm not familiar with Flow.

import { type SomeType } from "someModule";
export { SomeType };
let x: SomeType | undefined;

export { type SomeOtherType } from "someModule";

Placing the hint on a per-specifier basis will allow mixing of type and value import/reexports in a single import/export statement:

import { SomeValue, type SomeType, SomeOtherValue, type SomeOtherType } from "someModule";

export { AnotherValue, type AnotherType, YetAnotherValue, type YetAnotherType } from "someOtherModule";

Regarding unhappy paths:

  • Adding a type hint to a value should raise a type error "Value export must not be tagged as a type"
  • When isolatedModules is enabled type exports without a type hint should continue to raise a type error, though the message will likely need to be updated to something like "Cannot rexport type without a type hint"
  • When isolatedModules is disabled then there is no value to adding the type hint. We could disable adding the hints by throwing a TypeError "Type exports with type hint are only required in isolatedModules mode" but that feels pretty heavy handed. I think a better path is allowing the type hint from the compiler's perspective, while having a linting rule to that can can say if these type hints should be present or not (defaulting to present for isolatedModules is enabled and absent if disabled). This will help projects who wish to migrate from using tsc to a per-file compiler.

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, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Metadata

Metadata

Assignees

Labels

Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions