Skip to content

Allow narrowing dependent types from nested arrayΒ #56307

Closed
@lkuoch

Description

@lkuoch

πŸ” Search Terms

destructuring dependent types inside arrays

βœ… Viability Checklist

⭐ Suggestion

Allow the typescript compiler to infer from the motivating example to infer p1 to be number instead of number | undefined

πŸ“ƒ Motivating Example

// TSCONFIG: noUncheckedIndexedAccess is set to true

// I like go's handling of fallible functions where it returns a tuple of the result and the potential error
// I want to make a good DX over Promise.allSettled using the go philosophy but with ts checking
async function myAllSettled<T extends readonly unknown[]>(
  fn: () => T
) {
  const promises = await Promise.allSettled(fn());
  
  return promises.map((result) =>
    result.status === 'fulfilled'
      ? [result.value, undefined]
      : [undefined, new Error(String(result.reason))]
  ) as { [K in keyof T]: [Awaited<T[K]>, undefined] | [undefined, Error] };
}

async function test() {
  const [[p1, p1Error], _,] = await myAllSettled(() => [
    Promise.resolve(0), Promise.reject(1)
  ] as const);

  if (p1Error) return;

  // HELP!: How can I make (p1, p1Error) types be dependant so p1 can be inferred as `number` instead of `number | undefined`
  // I want to keep the dx of inlining the destructuring in line 18
  console.log(p1);
}

πŸ’» Use Cases

  1. I want to write a nice dx over Promise.allSettled returning a tuple of [value, error] such that they are dependent on each other
  2. I want to be able to preserve the inline destructuring so that typescript is able to infer the type of p1 as number instead of number | undefined
  3. A workaround is to not inline the destructuring fully (see below) but comes at the cost of a extra line and a hit to dx
    eg:
async function test() {
  const [p1Result, _,] = await myAllSettled(() => [
    Promise.resolve(0), Promise.reject(1)
  ] as const);

  // Destructure again on a new line
  const [p1, p1Error] = p1Result;

  if (p1Error) return;

  // p1 is now correctly inferred as `number` instead of `number | undefined`
  console.log(p1);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Help WantedYou can do thisPossible ImprovementThe current behavior isn't wrong, but it's possible to see that it might be better in some cases

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions