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

Narrowed type not "carried" iteratively #57690

Closed
eranhirsch opened this issue Mar 8, 2024 · 2 comments Β· Fixed by #57750
Closed

Narrowed type not "carried" iteratively #57690

eranhirsch opened this issue Mar 8, 2024 · 2 comments Β· Fixed by #57750
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@eranhirsch
Copy link

πŸ”Ž Search Terms

narrow, generic

πŸ•— Version & Regression Information

  • This changed between versions 5.3.3 and 5.4.2

⏯ Playground Link

https://www.typescriptlang.org/play?#code/PTAEF5NB1B5AlA0gZQpdH0CgsBMCmAxgDYCGATvqAGYCuAdoQC4CWA9vaCwM4AKZLerABGAKyJMAjAAosoULlJNSALlAMA1vTYB3egBosASjWLlXbqHhE25XAB5e5NgAd85JgE9E+T-vX0Wrr0AHwA3DgEJBRUhBzcTKAAtp4iopJqmtp6ESzUoNI8-KSCaRIyKWmSRkagAN5y8jS2BXH0CaAavqBs+QDaAESkA-4DwiOgA4QDALq1DU1NbR0E+G7kEMmpYpJ9XZ4zEYvyIIsAegD8jYvLiavrPp6W4BbFpWLl0vfutRegZcwAHT7bhffBrH6gNR9Q7XUAAXywiKwp3QoAAIrAAKLIAByABUYAhEGhMGTsKdYPRiJ4FHlqO58IwqMJ8EwdODOEwABZUABMXCSLmIlh4oB5VAA5kz3CxCKBCYJxbzxZ43P58AA3JmgHS8zgsRI8egAckStG4+FwgJtkSIZEoNAYzHYBr4AiEH2YfPs+JCsnkZlUASCekMJgUSlIFisNjsjmc6y8j38WWC4Tt0Udty2aT5mUC2XouXyhXdJU94m90kqYj5NXqcOoLWkOf2PX6QwmY270zmjeOoBz3w2L1roj5e18sMHpyalzh8mH4Ievmerw9AKYfLBEPIv3+XqYwLXu-WtWhM6aiMRQA

πŸ’» Code

// === WORKS =============

declare function isPlainObject1(
  data: unknown,
): data is Record<PropertyKey, unknown>;

declare const myObj1: unknown;
if (isPlainObject1(myObj1)) {
    for (const key of ["a", "b", "c"]) {
      const deeper = myObj1[key];
      //    ^?
      const deeperKeys = isPlainObject1(deeper) ? Object.keys(deeper) : [];
    }
}

// === DOESNT WORK ================
// Only difference between the 2 impls is the generic T in the type, even when it isn't used...

declare function isPlainObject2<T>(
  data: unknown,
): data is Record<PropertyKey, unknown>;

declare const myObj2: unknown;
if (isPlainObject2(myObj2)) {
    for (const key of ["a", "b", "c"]) {
      const deeper = myObj2[key];
      //    ^?
      const deeperKeys = isPlainObject2(deeper) ? Object.keys(deeper) : [];
    }
}

πŸ™ Actual behavior

The deeper variable, which is nested deeper from the narrowed type is inferred as any.

πŸ™‚ Expected behavior

It is the result of accessing a prop on a Record<PropertyKey, unknown> so is expected to be unknown.

Additional information about the issue

I maintain the Remeda utility functions library, I just got this reported here: remeda/remeda#559 and there are additional anecdotal reports that upgrading to typescript 5.4 breaks several of our types.

I couldn't find a reasoning to this issue, including any new changes to Typescript in 5.4 which might explain it.

I'm not sure my title makes sense for this bug, as I don't fully understand what's going on here, or even how to build a truly minimal example.

@RyanCavanaugh
Copy link
Member

Bisects to #57358

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Mar 8, 2024
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 5.5.0 milestone Mar 8, 2024
@mxschmitt
Copy link
Member

mxschmitt commented Mar 11, 2024

Looks like Playwright is also affected by this.

Minimal Reproduction on the Playground
Bisect: 2a0edf7...db3d54f
5.4.0-dev.20240214 bad
5.4.0-dev.20240213 good

Error: 'parents' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants