Christian Rodemeyer
Christian Rodemeyer

Reputation: 2058

Why does type inference from class constructor not work inside while loops

I have the following function that should list all top level folders in AWS S3 bucket. It uses the aws-sdk-js-v3 which itself is written in Typescript.

async function listTopLevelFolders() {
  let ContinuationToken: string | undefined = undefined
  do {
    // type inference does not work, command is of type any
    const command = new ListObjectsV2Command({       
      Bucket,
      ContinuationToken,
      Delimiter: '/',
    })
    const output = await s3Client.send(command)
    console.log(output.CommonPrefixes?.map((a) => a.Prefix))
    ContinuationToken = output.NextContinuationToken
  } while (ContinuationToken)
}

The problem is the line with const command = new ListObjectsV2Command(). I get the error

'command' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.

which I don't understand because it should be easy to infer that command is of type ListObjectsV2Command. Astonishingly, if I comment out the do {} while () loop type inference works as expected and the code compiles without errors

async function listTopLevelFolders() {
  let ContinuationToken: string | undefined = undefined
  // type inference works, command is of type ListObjectsV2Command
  const command = new ListObjectsV2Command({ 
    Bucket,
    ContinuationToken,
    Delimiter: '/',
  })
  const output = await s3Client.send(command)
  ContinuationToken = output.nextContinuationToken
}

I'm using Typescript Version 3.9.5 and I have enabled all Strict Type-Checking Options.

Upvotes: 1

Views: 252

Answers (1)

zamber
zamber

Reputation: 938

Typescript does type inference in loops and other control structures. Also there should be some type matching in ListObjectsV2Command for the input and output and in what s3Client.send accepts and returns. Try browsing type definitions for these classes to see how it clicks into place.

My best guess is that assigning undefined explicitly to ContinuationToken breaks type inference and leads to it resolving to any when it accepts an optional string. This along with the while loop and passing the inferred output to the input of the same constructor leads to this error.

Having it not assigned to undefined (let ContinuationToken: string;) should work then as it seems that the type will correctly match as string on subsequent runs and pass undefined on the first pass.

Upvotes: 1

Related Questions