Skip to content

Type-only import that merges with namespace cannot be used in a type position. #36397

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

Closed
rbuckton opened this issue Jan 24, 2020 · 2 comments
Closed
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@rbuckton
Copy link
Member

TypeScript Version: 3.8.0-dev.20200123

Search Terms: type only import merged namesapce

Code

// file1.ts
export interface Foo { }
export namespace Foo {
  export const x = 1;
}

// file2.ts
import type { Foo } from "./file1";

declare function f(): Foo; // (1)

Expected behavior:

  1. No error

Actual behavior:

  1. Error: Cannot use namespace 'Foo' as a type.

Playground Link:
Related Issues:

@likern
Copy link

likern commented Jan 31, 2020

I'd like to add some additional thoughts to this issue as they might be relevant.

I've found that even though modules are now preffered way to compose code over namespaces, there is still one feature, which doesn't allow to completely replace them.

It is an ability to structure types. In almost any application there is kinds of types.

  1. Types for modeling data (Tag)
  2. Types for modeling component properties in React (TagProps)
  3. Types for modeling callback data and functions - events (TagEvents)

If using only modules it's not possible to structure these kinds of types and addtional suffix (like <ComponentName>Props) have to be used to distinguish between them.

For example, I came up to this type structure in my app:

export declare namespace BottomSheetTypes {
  export interface Tag {}

  namespace Events {
    interface TagSelectionChanged {
      onSelectionChanged?: (data: Pick<Tag, 'id' | 'isSelected'>) => void;
    }
    ...
  }

  namespace Properties {
    type Tag = {
      id: number;
      isSelected: boolean;
      iconName: IconName;
      iconColor: string;
      label: string;
    } & Events.TagEvents;
  }
}

I could do this only using namespaces.

What about adding type namespaces which will only allow to use types / interfaces inside them?They can also be nested to better structure type hierarchy.

// file1.ts
export type namespace BottomSheetTypes {
  ...
}

// file2.ts
import type { BottomSheetTypes } from "./file1";

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Feb 26, 2020
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.9.0 milestone Feb 26, 2020
@andrewbranch
Copy link
Member

I never saw it at the time, but this was fixed by #36092 on the same day the issue was filed 😄

@andrewbranch andrewbranch added the Fixed A PR has been merged for this issue label Feb 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants