Skip to content
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

Non-exported recursive type alias is inlined until it falls back to any in declarations #58696

Open
dragomirtitian opened this issue May 29, 2024 · 3 comments
Labels
Bug A bug in TypeScript Help Wanted You can do this
Milestone

Comments

@dragomirtitian
Copy link
Contributor

πŸ”Ž Search Terms

declarations recursive types

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried (before 4.4 it was either a stack overflow crash or an error on the recursive type)

⏯ Playground Link

Playground Link

πŸ’» Code

// @declaration: true
// @filename: utils.ts 

type Recursive<T>  =  T extends Array<infer V>? Recursive<V>: T;

export const f = <T>(): Recursive<T> => { return null! } 

// @filename: index.ts 
import { f } from './utils';
export const a = f;

πŸ™ Actual behavior

In declarations, the type for a is printed as a: () => T extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? V extends (infer V)[] ? any : V : V : V : V : V : V : V : V : V : V : T;

πŸ™‚ Expected behavior

Recursive can't be represented without falling back to any (as seen above) so it should just be an error instead of silently to any

Additional information about the issue

Related to #55832

@jakebailey
Copy link
Member

Generally, I feel like it'd be even better to always emit some sort of declaration error whenever declaration emit synthesizes an any out of nowhere...

@dragomirtitian
Copy link
Contributor Author

I'll open a PR after 5.5. I tried locally and there are several places that now have errors, but in my opinion they are all good. Maybe we have just a carveout if someone is not using noImplicitAny (although hopefully nobody is actually doing that πŸ˜…)

@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript Help Wanted You can do this labels Jun 14, 2024
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Jun 14, 2024
@waynebloss
Copy link

waynebloss commented Jun 19, 2024

I think this is the same issue I'm having, but I'm not sure.

Problem description within...
// Exported from `@mylib/dev/jrfs`:

export interface FileOf<D = unknown, M = unknown> {
  data: D;
  meta: M;
}
export type FileTypes<FT> = Record<keyof FT & string, FileOf>;

// Exported from `@mylib/dev/features/db`:

export interface DbDesign {
  db: DbModel;
}

export interface DbDesignFileMeta {
  test: boolean;
}

export type DbDesignFile = FileOf<DbDesign, DbDesignFileMeta>;

In the app project which imports from @mylib, when I use the DbDesignFile type exported from @mylib/dev, then VS Code shows the wrong type (const data: FileOf<DbDesign, DbDesignFileMeta>) in the tooltip and autocomplete doesn't work and it acts like the found data is any...

import { DbDesignFile } from "@mylib/dev/features/db";

interface ProjectFileTypes {
  db: DbDesignFile;
}

// Try it out:

class Yada<FT extends FileTypes<FT>> {
  async findTypes<K extends keyof FT & string>(
    type: K,
  ): Promise<
    Array<{
      node: any;
      data: Required<FT[K]>["data"];
    }>
  > {
    return [];
  }
}
const yada = new Yada<ProjectFileTypes>();
const nodes = await yada.findTypes("db");
for (const { node, data } of nodes) {
  // TODO: Figure out why `data` is treated like `any` here:
  console.log("FOUND", node.name, data);
}

However, if I re-define the DbDesignFile type alias in my app project then data from the yada.findTypes call above correctly shows and autocompletes type DbDesign...

import { FileOf } from "@mylib/dev/jrfs";
import { DbDesign, DbDesignFileMeta } from "@mylib/dev/features/db";

type DbDesignFile= FileOf<DbDesign, DbDesignFileMeta>;

interface ProjectFileTypes {
  db: DbDesignFile;
}

UPDATE: I figured out my own issue - my library's type declarations were being created with import type {...} from "@/jrfs"; because I don't have anything in place to fix tsc created alias import paths. Once I changed those to use relative import paths it worked. So, never mind, sorry for the noise!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Help Wanted You can do this
Projects
None yet
Development

No branches or pull requests

4 participants