Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type-only import prevents declaration of a value with the same name #40583

Closed
1000hz opened this issue Sep 16, 2020 · 7 comments
Closed

type-only import prevents declaration of a value with the same name #40583

1000hz opened this issue Sep 16, 2020 · 7 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@1000hz
Copy link

1000hz commented Sep 16, 2020

TypeScript Version: 4.1.0-dev.20200915

Search Terms: ts1361 type-only import type 'Foo' cannot be used as a value because it was imported using 'import type'.

Code

import type { Foo } from "./Foo";

function Foo(): Foo {
  return {
    name: "index.ts"
  };
}

Foo(); // 'Foo' cannot be used as a value because it was imported using 'import type'.ts(1361)

Expected behavior: Since the import type only creates a symbol in the type realm, I expect to be able to create the same symbol in the value realm without conflict. Especially since it's possible to declare the same symbol as both a type and value from within a single file.

Actual behavior: An error is raised: 'Foo' cannot be used as a value because it was imported using 'import type'.ts(1361), which makes this behavior seem very much intended, though that seems to violate the feature's stated intent. From the description of the feature's Type semantics from #35200:

If the symbol does have a value side, name resolution for that symbol will see only the type side.

Playground Link: https://codesandbox.io/s/wizardly-chatelet-h8zkg?file=/src/index.ts

Related Issues: #35200

cc: @andrewbranch

@DanielRosenwasser
Copy link
Member

This is correct, Foo still potentially refers to a value which can only be used in non-emitted positions. If you want to separate the two, consider

import type { Foo as _Foo } from "./Foo";

type Foo = _Foo;
function Foo(): Foo {
  return {
    name: "index.ts"
  };
}
Foo();

or

type Foo = import("./Foo").Foo;
function Foo(): Foo {
  return {
    name: "index.ts"
  };
}
Foo();

@DanielRosenwasser DanielRosenwasser added the Working as Intended The behavior described is the intended behavior; this is not a bug label Sep 16, 2020
@DanielRosenwasser
Copy link
Member

Letting @andrewbranch correct me if I'm mistaken though

@andrewbranch
Copy link
Member

You got it right 👍

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@mastarija
Copy link

This is correct, Foo still potentially refers to a value which can only be used in non-emitted positions. If you want to separate the two, consider

import type { Foo as _Foo } from "./Foo";

type Foo = _Foo;
function Foo(): Foo {
  return {
    name: "index.ts"
  };
}
Foo();

or

type Foo = import("./Foo").Foo;
function Foo(): Foo {
  return {
    name: "index.ts"
  };
}
Foo();

Sorry for bringing this up after four years, but I'm interested in what way can Foo still be a value if we've explicitly imported it as a type, and there's no e.g. value of the same name as the type in the imported module?

@RyanCavanaugh
Copy link
Member

The best way to understand this is that the correct interpretation isn't "Import the type meaning of Foo", it's "Import Foo for use in type positions". For example, let's say you have a class exported in one file

// foo.ts
export class Foo {
  static x = "bar";
}

You can import it elsewhere and use it as a value, in type positions:

import type { Foo } from "./foo.js";
function something(f: typeof Foo) { // <- *value* reference on Foo
  return f.x;
}

@mastarija
Copy link

Aha. So this is more a feature for avoiding unnecessary imports in the built code. If I want to use a value Foo just to get it's type, then I use import type and I can use the value only on the type position, and this value won't actually be included in the final built JS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

6 participants