question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow importing both type entity and value entity for "const enum" through "import type"

See original GitHub issue

Search Terms

const enum, import, importsNotUsedAsValues

Scenario

I am a library developer, and there is a really large types.ts file in my project, which contains many interface, type, and const enum, defining a large part of types of the project, just like you do (typescript/src/compiler/types.ts).

Recently I turned on the compiler option importsNotUsedAsValues, and found some problems about const enum.

Original fileA.ts

import {
    TypeA, TypeB, TypeC,
    ConstEnumD, ConstEnumE,
} from './types.ts';

------------------

Current fileA.ts

import type {
    TypeA, TypeB, TypeC,
} from './types.ts';
import {
    ConstEnumD, ConstEnumE,
} from './types.ts';

Because the entities of enum belong to both type scope and value scope, I have to import them separately if I want to use them as values.

Now I have to separate the import of type const enum from a lot of names file by file, which is really a lot of work.

What’s worse, after turning on importsNotUsedAsValues, TypeSciprt unnecessarily write require('./types.js') into fileA.js though the generated code did not access any property of require('./types.js'). In other words, it makes types.ts seems to have side effects. And this feature may affect the file reference relation of the project and lead to incorrect Rollup order.

In my mind, accessing the const enum entity in value scope is a kind of special behavior and is something that will be replaced in compile-time. There should be a way to import both type entity and value entity of const enum from a file without really requiring the file, especially when the file really has side effects.

Solution

There are 2 ways to solve this problem:

1. import both type and value for const enum through import type

import type { ConstEnumA } from './types';
//       Type↓        Value↓
const a: ConstEnumA = ConstEnumA.propA;

// ts not emit "  require('./types')  "

I prefer this method because I will not need to greatly change my code.

Breaking change?

Name conflicts may occur if there was already a name in value scope which was same with ‘ConstEnumA’, but I think this is very very rare and will be prevented by linter usually. An extra compiler option can be provided to solve this.

2. check const enum in value-import

// importsNotUsedAsValues is still on

import { ConstEnumA } from './types';
//       Type↓        Value↓
const a: ConstEnumA = ConstEnumA.propA;

// ts find just "ConstEnumA" is used and it is `const enum`
// not emit "  require('./types')  "

Breaking change?

Yes. Now TS do not emit require('...') though value-import exists in the code.

Examples

A complete example of Solution 1:

import type {
    TypeA,
    TypeB,
    TypeC,
    ConstEnumA,
    TypeD,
    TypeE,
    TypeF,
    ConstEnumB,
    TypeG,
    TypeH,
    TypeI,
    ConstEnumC,
    ConstEnumD,
    TypeJ,
    TypeK,
} from './types';

const b: ConstEnumB = ConstEnumB.propA;
// compiler: OK, 0 error(s). not emit "  require('./types.js')  "

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.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:8
  • Comments:14 (5 by maintainers)

github_iconTop GitHub Comments

5reactions
jdomcommented, Feb 17, 2021

Since you are gauging demand for it, we are also running into this in the Azure Portal. We have a ton of dynamically loaded modules (where import type is useful) and use const enums a lot. We have to workaround this issue with non-ideal approaches that could lead to someone mistakenly importing a module explicitly and causing tons of bundling side-effects

2reactions
SohumBcommented, Aug 31, 2021

Just adding a datapoint here as well. Our project makes extensive use of a large number of enums in a dependency, and this is directly impeding our efforts to bundle-split that dependency until it’s actually needed, instead of just being needed to grab a constant string.

Read more comments on GitHub >

github_iconTop Results From Across the Web

typescript - How to import an Enum - Stack Overflow
I'm using global TS importing and TS can't see the exported enum that I have put in a different file for this very...
Read more >
Handbook - Enums - TypeScript
The usual way to unambiguously elide imports, type-only imports, does not allow const enum values, currently. Here are two approaches to avoiding these...
Read more >
Direct FeatureScript imports - Onshape
In a Feature Studio, you can import another Onshape tab with the import ... The value is of a type corresponding to the...
Read more >
TypeScript errors and how to fix them
error TS1361: ' Range ' cannot be used as a value because it was imported using 'import type'. Broken Code ❌. 1 2...
Read more >
Entities - typeorm - GitBook
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm" ... string[]|AnyEnum - Used in enum column type to specify list of allowed enum values....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found