-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Constants + Generic causing TS4023 ("but cannot be named") #37888
Comments
Interestingly, changing export type ReturnType1 = WrapType<ReturnType2>; works, even though it should be exactly the same, except we go through one additional level of indirection. I'm also not sure why, but the generated declaration for import { ReturnType2 } from './lib';
export declare const impl1: () => import("./lib").WrapType<ReturnType2>;
export declare const impl2: () => ReturnType2; Why did |
I'm able to reproduce it without generics. Repro here: https://github.com/cyberuni/typescript-37888 // types.ts
export const typeSym = 'type'
// null.ts
import { typeSym } from './type'
export const nil = { [typeSym]: 'null' as const }
// optional.ts
import { nil } from './null'
export const optional = { nil } // 'typeSym' cannot be named I explain it in detail here: |
I'm running into this error while trying to emit declarations on code using unique symbols. Simple repro follows: a.ts: export const S = Symbol();
export const a = { [S]: null }; b.ts: import { a } from './a';
export const b = a;
// ^ Exported variable 'b' has or is using name 'S' from external module "./a" but cannot be named. ts(4023) The emitter seems to be mainly failing on object keys. If instead I rewrite a.ts as: export const S = Symbol();
export const a = { fn: (p: typeof S) => {} }; Then it works fine and the d.ts looks like this: export declare const b: {
fn: (p: typeof import("./a").S) => void;
}; |
Just got hit by this again while trying to use references on our project. Made a search, and found my own issue 😄 |
Ran into this with symbols just now in composite projects using project references and TypeScript v4.2.3 (haven't tried v4.2.4 which just came out yet, but based on the release notes I don't expect the behavior to be different). In this example one project ( // a.ts
const A = Symbol('hey');
export function create() {
return {[A]: true]};
}
// a.d.ts
declare const A: unique symbol; // etc...
// b.ts
import {create} from 'a.ts';
const b = create(); // TS4023 "has or is using name 'A' from external module "..." but cannot be named
export default b; // Note the error only happens if you export; otherwise the call to `create()` is fine. In this case, I can workaround by using a string key instead of the symbol; eg. // a.ts
const A = 'hey'; // No TS4023 any more. |
As noted in this issue: microsoft/TypeScript#37888 And specifically in my comment: microsoft/TypeScript#37888 (comment) There is a problem in the TypeScript compiler involving indirect references to unique Symbol types defined in projects connected by via project references. In short, `frontend-js-state-web` uses private `Symbol` instances as an implementation detail, and these wind up in the type declaration files as, eg: declare const ATOM: unique symbol; So, when another project attempts to use a function like `Liferay.State.atom()` that returns an object of a type involving that symbol, TS may complain with: TS4023: Exported variable 'blah' has or is using name 'ATOM' from external module "path/to/State" but cannot be named. The exact conditions required to trigger this are subtle, because using `atom()` is working fine in places like the `frontend-js-react-web` tests. My theory is that those work fine because the uses are all internal, so TS doesn't need to emit any type information involving the symbol. But in the case of `item-selector-taglib`, which I am working on for the purposes of this LPS, I have to export the atom, and that's when the error pops up. Remove the `export` and there is no error. So the problem is that TS has to emit a `.d.ts` file and it can't, because it can't "see" the value of the symbol in the consuming module. We can make the error go away like I am here in this commit, switching from a symbol to a plain old string. These objects are read-only and cannot be manipulated directly, so this is going to be fine, although I did like the way the symbol keys were "invisible" from the outside.
As noted in this issue: microsoft/TypeScript#37888 And specifically in my comment: microsoft/TypeScript#37888 (comment) There is a problem in the TypeScript compiler involving indirect references to unique Symbol types defined in projects connected by via project references. In short, `frontend-js-state-web` uses private `Symbol` instances as an implementation detail, and these wind up in the type declaration files as, eg: declare const ATOM: unique symbol; So, when another project attempts to use a function like `Liferay.State.atom()` that returns an object of a type involving that symbol, TS may complain with: TS4023: Exported variable 'blah' has or is using name 'ATOM' from external module "path/to/State" but cannot be named. The exact conditions required to trigger this are subtle, because using `atom()` is working fine in places like the `frontend-js-react-web` tests. My theory is that those work fine because the uses are all internal, so TS doesn't need to emit any type information involving the symbol. But in the case of `item-selector-taglib`, which I am working on for the purposes of this LPS, I have to export the atom, and that's when the error pops up. Remove the `export` and there is no error. So the problem is that TS has to emit a `.d.ts` file and it can't, because it can't "see" the value of the symbol in the consuming module. We can make the error go away like I am here in this commit, switching from a symbol to a plain old string. These objects are read-only and cannot be manipulated directly, so this is going to be fine, although I did like the way the symbol keys were "invisible" from the outside.
As noted in this issue: microsoft/TypeScript#37888 And specifically in my comment: microsoft/TypeScript#37888 (comment) There is a problem in the TypeScript compiler involving indirect references to unique Symbol types defined in projects connected by via project references. In short, `frontend-js-state-web` uses private `Symbol` instances as an implementation detail, and these wind up in the type declaration files as, eg: declare const ATOM: unique symbol; So, when another project attempts to use a function like `Liferay.State.atom()` that returns an object of a type involving that symbol, TS may complain with: TS4023: Exported variable 'blah' has or is using name 'ATOM' from external module "path/to/State" but cannot be named. The exact conditions required to trigger this are subtle, because using `atom()` is working fine in places like the `frontend-js-react-web` tests. My theory is that those work fine because the uses are all internal, so TS doesn't need to emit any type information involving the symbol. But in the case of `item-selector-taglib`, which I am working on for the purposes of this LPS, I have to export the atom, and that's when the error pops up. Remove the `export` and there is no error. So the problem is that TS has to emit a `.d.ts` file and it can't, because it can't "see" the value of the symbol in the consuming module. We can make the error go away like I am here in this commit, switching from a symbol to a plain old string. These objects are read-only and cannot be manipulated directly, so this is going to be fine, although I did like the way the symbol keys were "invisible" from the outside.
Workaround to the "symbol-as-key" variant of this issue: if you give TS some non- Failing Pattern// a.ts
export const A = Symbol("A");
export function create() {
return { [A]: true };
}
// b.ts
import { create } from "./a";
export const b = create(); // TS4023: Exported variable 'b' has or is using name 'A' from external module... Workaround Pattern// a.ts
export const A = Symbol("A");
export interface WithAField<T> {
[A]: T;
}
export function create(): WithAField<true> {
return { [A]: true };
}
// b.ts
import { create } from "./a";
export const b = create(); // Emits as import("./a").WithAField<true> |
Is there a falg/ config to disable these errors: TS4023 |
For anyone running into this issue while dealing with exporting types that make use of
Example
// some unique symbols the compiler is complaining about elsewhere
declare const TYPE: unique symbol;
declare const ID: unique symbol;
// perhaps a utility type being used to create special types
type Datatype<es_type, clarifier extends string> = {
[TYPE]: es_type;
[ID]: clarifier;
} & es_type;
// the actual type being used elsewhere
export type Usd = Datatype<string, 'usd'>
import type {Usd} from './datatypes';
// where the error is being shown
export function cast(input: string): Usd { ... } The ProblemAs others have pointed out, this is happening because the system is breaking down the type of The WorkaroundIn export type Usd<subtype extends string=string> = Datatype<subtype, 'usd'>; |
TypeScript Version: 3.8, but also the 3.9 beta
Search Terms: ts4023 cannot be named constant
Code
Create a tsconfig with
declaration: true
. Then, inmain.ts
:In
lib.ts
:Old instructions (don't repro anymore)
Create a tsconfig with
declaration: true
. Then, inmain.ts
:In
lib.ts
:Expected behavior:
The file should be properly compiled.
Actual behavior:
TypeScript reports a diagnostic:
Playground Link: n/a
Related Issues: n/a
The text was updated successfully, but these errors were encountered: