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

as any unexpectedly breaks function parameter type inference #54987

Closed
sodatea opened this issue Jul 12, 2023 · 2 comments
Closed

as any unexpectedly breaks function parameter type inference #54987

sodatea opened this issue Jul 12, 2023 · 2 comments
Labels
Not a Defect This behavior is one of several equally-correct options

Comments

@sodatea
Copy link

sodatea commented Jul 12, 2023

Bug Report

🔎 Search Terms

as any
type casting
function parameter
generic type inference

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about generics and any and type casting

⏯ Playground Link

💻 Code

type UserConfig = {
  target: "es5" | "es2015" | "esnext";
  fileName: (format: string) => string;
};
type UserConfigExport = UserConfig | ((env: object) => UserConfig);

function defineConfig<T extends UserConfigExport>(config: T): T {
  return config;
}
defineConfig(() => ({
  target: "es5",
  fileName: (format) => `index.${format === "es" ? "mjs" : "cjs"}`,
}));


defineConfig(({
  target: "es5",
  // Somehow the type inferrence of this function becomes incorrect
  fileName: (format) => `index.${format === "es" ? "mjs" : "cjs"}`,
})) as any;

// Shouldn't error here, either
defineConfig(() => ({
  target: "es5",
  fileName: (format) => `index.${format === "es" ? "mjs" : "cjs"}`,
})) as any;

🙁 Actual behavior

The ones with an as any typecasts failed.

🙂 Expected behavior

All defineConfig calls should pass.

@RyanCavanaugh RyanCavanaugh added the Not a Defect This behavior is one of several equally-correct options label Jul 12, 2023
@RyanCavanaugh
Copy link
Member

Because T is in the return position, a contextual type on the function call acts as an inference candidate, so having as any here is the same as if you had written

defineConfig<any>(() => ({
  target: "es5",
  fileName: (format) => `index.${format === "es" ? "mjs" : "cjs"}`,
}));

which displays the same behavior.

@sodatea
Copy link
Author

sodatea commented Jul 14, 2023

Thank you so much for the explanation!
It does make sense once I replace as any with <any>.

I didn't realize the connection because the code came from a refactor of the function from non-generic to generic types 😂

@sodatea sodatea closed this as not planned Won't fix, can't repro, duplicate, stale Jul 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Not a Defect This behavior is one of several equally-correct options
Projects
None yet
Development

No branches or pull requests

2 participants