microsoft / microsoft/TypeScript

Mapped types created from reverse mapped types with union/intersection constraints don't have declaration linked

Open
#57,211 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Domain: Mapped Types Help Wanted Possible Improvement
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
1d 19h
Merged PRs (30d)
117

Description

🔎 Search Terms

reverse mapped type go to definition union intersection constraint declarations

🕗 Version & Regression Information
  • This is the behavior in every version I tried
⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.4.0-dev.20240128#code/C4TwDgpgBAysBOBLAxsA8mYiD2A7AcgIYC20AvFAES7YCSxYANiosAIK4iVQA+VAzghTB8AV0aMAwgAsIyANb9KAbgBQiXMAjwAZoWTRJ2BokbaMWPPygBvVVAdRE-bI0JaAJgFlsH8RH4AfgAuKAAjbFcIQlw1RygaeiYWdk4Q8MizGLjHQSRUdIio7PtcoVQxCRk5RULM6NjShwA3bTD3RGIfPzMYEE1CAA864saAX1VQSCgjEzN4CxxcAGkIEGsKeTXsHVsmqABtZadcKC2QHZnjMFNzTCXrQms8jQBzKAhBrVwPa2PAhIQVrwKChZYAXVCMRAajGag8cjc8GgOlEuFQSygrwgwDg+XQ9zwADVCIxRBAABTIa63BaE3D8UKzG7zRZWAA0UB0bleoTxwjZBBIEAAlKEillGgjkEiUWiMXgoMhke4IMzRJ5mbTBfwADwAFQ+XwgP2sACU5Nh4B5dS9cK9OVrWfTVusDuCAHweinYemMvbxI4nKAU86XQ0AMiuczulhWa34It4sHKBLjRFIkID8UcCMgPxNyEQAVC+qO4JyOaV1w1EBJZIgoSpNOdcf9AAUUPJdU7Yw9Occ+GWIQdcKJiGFtJ6k2QPVAAKKDGWiBE9lt9qzlzlohE6DQQDweytQOGqMZiqBTCCXX1ttSqakM4DVhi1jxQCjK6JadWa9d0tsKTsBxnFcVVvF8fx-WA3MIHzBF0WLf0DkoYF2iwLpIN6fpgCGShwXZfZqVfLR63JJtiJZDcGRnOcYPiZFgFEeBTgAQlYil9niSjtT9AA6UC3E8booN4PgeNbB4+LQjpMJ6CA+gGQYuKgEVjzGQiHA00pEgYZgi1SEBQnoqA8xNBCixLQ5KBeVB8M0xxKNrMjGxDCTqMTD86JUxjmNObFcVTQUXObGMAP7KhdOSAyOC4NT9m0rSHNskRxCkWQFGg-YzILRCrJQlL7KImtSNJci3P-HVaOzBicT8rEcX5VBgrKyl3PCjkBFTSp0pqJR4viRKT0I8970fQQGuAWh+GmsDhKwgIPxfMA3wElwhIPESzH4AB6AAqABGPadr4pzSobVRLquq6gA

💻 Code
type StrictOptionName = "noImplicitAny" | "strictNullChecks";
interface CompilerOptions {
    isolatedModules?: boolean;
    noImplicitAny?: boolean;
    strict?: boolean;
    strictNullChecks?: boolean;
    verbatimModuleSyntax?: boolean;
}
type CompilerOptionKeys = keyof {
    [K in keyof CompilerOptions as string extends K ? never : K]: any;
};
declare function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean;
declare function createComputedCompilerOptions<T extends Record<string, CompilerOptionKeys[]>>(options: {
    [K in (keyof T & CompilerOptionKeys) | StrictOptionName]: {
        dependencies: T[K];
        computeValue: (compilerOptions: Pick<CompilerOptions, K | T[K][number]>) => Exclude<CompilerOptions[K], undefined>;
    };
}): typeof options;

const computed = createComputedCompilerOptions({
  isolatedModules: {
    dependencies: ["verbatimModuleSyntax"],
    computeValue: (compilerOptions) => {
      return !!(
        compilerOptions.isolatedModules || compilerOptions.verbatimModuleSyntax
      );
    },
  },
  noImplicitAny: {
    dependencies: ["strict"],
    computeValue: (compilerOptions) => {
      return getStrictOptionValue(compilerOptions, "noImplicitAny");
    },
  },
  strictNullChecks: {
    dependencies: ["strict"],
    computeValue: (compilerOptions) => {
      return getStrictOptionValue(compilerOptions, "strictNullChecks");
    },
  },
});

const getIsIsolatedModules = computed.isolatedModules/*1*/.computeValue
🙁 Actual behavior

Go to definition doesn't go anywhere at marker 1

🙂 Expected behavior

Go to definition should go to the property at the line 21

Additional information about the issue

modifiersType for this mapped type is unknown. I think that potentially the modifiers type when iterating over any reverse mapped type (when reversed.mappedType === (mappedType.target || mappedType) could use that reversed.source as the modifiers type. If not that then at least declarations could be outsourced to that type for linking properties.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked TypeScript Playground reproduction and inspect the go-to-definition request at marker 1, focusing on the reverse mapped type and its modifiersType. Compare the result with the expected property on line 21. Done means go-to-definition from computed.isolatedModules.computeValue resolves to that property declaration.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.