Symbol properties on objects are imported by type and not by value when auto-completed
🔎 Search Terms
symbol ( label:"Domain: Completion Lists" OR label:"Domain: TSServer" )
symbol verbatimModuleSyntax
verbatimModuleSyntax
🕗 Version & Regression Information
I can reproduce this in 4.4 (the first version to support symbol indices according to https://stackoverflow.com/a/649435420) and f1d2494e91a7ce04feace304d1a3bce36ba8746a (main at the time of writing)
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
symbol
⏯ Playground Link
https://github.com/sadan4/ts-symbol-auto-import-repro
💻 Code
// exportsSymbol.ts
export const SYM_FOO_BAR = Symbol.for("foo.bar");
export interface ObjWithSym {
[SYM_FOO_BAR]: any;
}
// usesSymbol.ts
import type { ObjWithSym } from "./exportsSymbol";
export declare const thing: ObjWithSym;
function main() {
// uncomment the following line and try tab-completing SYM_FOO_BAR
// thing.
}
After autocompleting, typescript will update the file to be
import type { ObjWithSym, SYM_FOO_BAR } from "./exportsSymbol";
export declare const thing: ObjWithSym;
function main() {
// uncomment the following line and try tab-completing SYM_FOO_BAR
thing[SYM_FOO_BAR]
}
🙁 Actual behavior
SYM_FOO_BAR is imported by type and not by value
🙂 Expected behavior
ObjWithSym remains imported by type while SYM_FOO_BAR is imported by value
Additional information about the issue
When verbatimModuleSyntax and erasableSyntaxOnly are enabled, any import will import as type, not just adding to existing imports.
Updating the imports with a quick-fix or tab-completing the computed property works as expected in both versions.
This seems like an issue with auto-importing symbols while an existing type-only import block exists, rather than with any specific compiler options.
Interesting bug.
Copilot: This is specific to the case where we have a symbol name coming from a dot completion. The bug is in the language service; we're adding a type import when it should be a value import. Write a fourslash testcase, verify it fails, then fix the bug.
Ensure that your fix is consistent with the fact that the non-indexed form
import type { ObjWithSym } from "./exportsSymbol";
export declare const thing: ObjWithSym;
function main() {
// uncomment the following line and try tab-completing SYM_FOO_BAR
// thing.
// const m = SYM_FOO_BAR
}
produces the merged import
import { SYM_FOO_BAR, type ObjWithSym } from "./exportsSymbol";
Other instructions:
- Read the contents of CONTRIBUTING.md, it has instructions on how to run a single test, handling baselines, etc
- Run
hereby lintandhereby formatbefore you're done - Only add testcases in
tests/cases/compilerortests/cases/fourslash. Do not write direct unit tests. - Running a set of tests may take up to 4 minutes
- A full test run may take up to 15 minutesAdd commentMore actions
- Maintainer comments in the issue should generally take priority over OP's comments
- Maintainers might give you hints on where to start. They are not always right, but a good place to start
Your workflow should be:
- Make a testcase that demonstrates the behavior. Run it (by itself) and review the baselines it generates to ensure it demonstrates the bug. Add the test and its baselines in one commit
- Fix the bug by changing code as appropriate. Put this fix in another commit
- Run the test you wrote again and ensure the baselines change in a way that demonstrates that the bug is fixed. Put this baseline diff in its own commit
- Run all other tests to ensure you didn't break anything. Some collateral baseline changes are normal, put these diffs in another commit