Skip to content

Narrowed type not "carried" iterativelyΒ #57690

@eranhirsch

Description

@eranhirsch

πŸ”Ž 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.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions