-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
[request] allow export type * from
#37238
Comments
Any news on this topic? |
In addition to all the usecases that P.S: the number of upvotes and likes shows the community opinion. I think "Awaiting more feedback" label should be removed. @RyanCavanaugh |
Just adding my use case here, I maintain a quite popular library (Popper) and I need a way to expose the TS types like I do in Flow (the system used to type the codebase). In Flow I can do |
I want to use it to pin dependency versions in Deno... wonder if there's any workaround because I feel like most alternative solutions are very not ergonomic |
Stumbled upon this issue just now. My use case is that there are definition files // thing.type.ts
type Primitive = string | number | boolean; // not exported
export type ThingPropConstraint = Primitive | object;
export interface Thing<Prop extends ThingPropConstraint> {
prop: Prop;
} // value.ts
export const value = 42; // index.ts
export * from "./thing.type";
export * from "./value"; Since Eventually, I expect type exports to be removed from // (output excerpt)
__exportStar(require("./thing.type"), exports); // Error: Cannot find module './thing.type'
__exportStar(require("./value"), exports); I'd like to enforce TypeScript to remove this export construct: // index.ts
export type * from "./thing.type";
export * from "./value"; The point of this example is that definition files can define more than one entity, and the information about the exact entities being exporting from a definition file must be preserved in this file (SRP), so re-exporting them must be done using an "export start" kind of export; otherwise, adding another definition will result in constant going back-and-forth between definition files and entry point file. |
@bluelovers Can I ask you to properly fill all the sections in the original comment (search terms, examples, checklist)? |
Any plans to implement this feature? |
I'm re-exporting type-utilities, keeping the related files as |
I just stumbled upon this. We have a file that only contains type annotations (https://github.com/babel/babel/blob/main/packages/babel-types/src/ast-types/generated/index.ts), and we currently re-export it internally using When publishing, we strip away TS types and compile to CJS. The types-only files becomes an empty CJS module, and our entry point ends up having some unnecessary code for Apparently, that empty CJS file causes problems with some tools (babel/babel#14634, https://stackoverflow.com/questions/71045195/cannot-build-run-devserver-cause-of-babel-loader, https://openclassrooms.com/forum/sujet/babel-loader-not-working, kriszyp/lmdb-js#51). It's a bug with those tools, but it would be nice if we could entirely avoid it by marking that re-export as type-only since it's a file that is not needed at runtime. |
@nicolo-ribaudo not sure I follow; |
It would elide the unnecessary require(), and avoid loading the empty file unnecessarily. |
Any updates on implementing this? |
Are there any workarounds to this, besides removing the |
I’m planning to investigate implementing this in the release after 4.9. |
My use case for this is that I'm using: https://github.com/acacode/swagger-typescript-api to generate types from swagger specs. The output file has a combination of types and code and I'd like to be able to export all types in one statement from module wrapping the generated code (so that I don't depend on the generated code directly). Currently, I have to remember to export any newly generated types. I would like to |
Just to be clear, // client.ts
export interface Foo {}
export function foo() {}
// exporter.ts
export type * from "./client";
// consumer.ts
import { Foo, foo } from "./exporter"; // ok
let x: Foo; // ok
let y: typeof foo; // ok
foo(); // error: 'foo' cannot be used as a value because it was exported using 'export type'. This is why I was hesitant to implement this feature; because people seem to want to read it as “export all the types,” but that’s inconsistent with what any other form of |
@andrewbranch thanks for the clarification. Ok it's true that I had in mind "types only export"... but now that I think about it - "export everything as a type only export" would also work well... in my case at least: // api-client module:
import { Api } from "./gen/api";
export const client = new Api();
// Anything which is callable code gets exported normally:
export const login = require2XX(client.login.loginCreate);
export const getUser = require2XX(client.user.userList);
// ...
// This is what needs manual intervention every time a new type is generated from spec files:
export type {
GetUserResBody,
LoginReqBody,
Theme,
User,
} from "./gen/api";
// I would like to replace with:
export type * from "./gen/api"; Anything which is exported by export const getUser = require2XX(client.user.userList);
I have not thought much about this - but isn't this a "superset"... i.e. even if people think of it as "export all the types" - that seems correct enough. In fact it's export everything but can only use everything as types so you give me the benefit of e.g. using Does that make sense? Thanks |
Yes, that’s the right way to think about it. The only downside I can think of is that you’ll see the values in named import completions. It doesn’t sound like a huge deal but a lot of people rely heavily on completions to understand TypeScript’s view of the world, so I can see how it would be confusing to someone who expected only types to show up. |
@andrewbranch true that - a lot to think about 😓 I am still in favour of adding this; but I'm also not maintaining any of this 😅 Re the confusion concern - explaining the semantics of
If it's any consolation - it makes perfect sense once you know |
@andrewbranch Is there a technical reason that I know that personally I would never use What I'm getting at is: could (If not, I'd still happily take |
Sidebar: if you're implementing |
The first draft of type-only imports filtered symbols down to types. We quickly got feedback that this prevented you from accessing class constructor types: import type { SomeClass } from "./c";
function makeInstance(SomeClassConstructor: typeof SomeClass): SomeClass {
// ^^^^^^^^^
// Cannot find name 'SomeClass'
return new SomeClassConstructor();
}
Is it possible to make
👍 That should come for free.
It will be a type-only export of a namespace named import * as Mod from "mod";
export type { Mod };
// or equivalently
import type * as Mod from "mod";
export { Mod }; |
Ah, that makes sense. Thanks for the explanation. It's a bit unfortunate, but given that constraint I see why you have to include values in
Yup, sounds good. |
I would appreciate some help testing #52217 if anyone is interested in trying this out early. |
Search Terms
export type
Suggestion
allow
export type * from
Use Cases
https://github.com/bluelovers/ws-ts-type/blob/master/packages/ts-type/index.ts
Examples
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: