0

I frequently run into this pattern:

function f() : VeryLongOrComplexType[] {
   const arr : VeryLongOrComplexType[] = []
   for (...) {
      ...
      arr.push(...)
   }
   return arr;
}

My focus is on

const arr : VeryLongOrComplexType[] = []

If I don't specify a type, it assumes arr's type is never[] and gives me an error at arr.push(...)

But I also feel like that arr's type could be inferred from either the .push or from the return type, but it's not.

Is any configuration through which I could just omit type declaration at the time of array declaration? e.g. const arr = [] instead of const arr : VeryLongOrComplexType[] = []?

Here's a reproduction of the issue as prompted by the comments. I suspect it has something to do with noImplicitAny configuration.

a screenshot of about ts playground link

2
  • 1
    I can't reproduce your issue. Perhaps you could provide a minimal reproducible example suitable for dropping into a standalone IDE that demonstrates the problem you're seeing? Otherwise you might not get a helpful answer. Commented Oct 31, 2021 at 14:54
  • I tried re-producing it in the playground. I added some complexity to your minimal example, but it seems that it has something to do with noImplicitAny configuration and apart from that maybe everything else is fine. I still don't understand what's happening. Commented Nov 1, 2021 at 9:13

1 Answer 1

1

You can pass as an argument an element which you want a push to arr:


function f<T>(elem: T): T[] {
  const arr: T[] = []
  arr.push(elem)
  return arr;
}

There is no other approach to infer arr type from push because push is already used on arr so it need to know the type.

Since you are iterating over some data structure I think it worth using reduce or map here:

const obj = {
  age: 42,
  name: 'John'
}

const f = () =>
  Object.keys(obj)
    .reduce<string[]>((acc, elem) => [...acc, elem], [])

As you might have noticed, you still need to explicitly type string[] because TS always infers empty array as a never[].

If you provide reproducible example I think you will get more meaningful answer.

UPDATE

In this example:

interface VeryLongOrComplexType { a: string }
const something: (x: number) => Promise<boolean> = null!
const someList: number[] = null!

async function f(): Promise<VeryLongOrComplexType[]> {
  const arr = []
  for (const x of someList) {
    if (await something(x)) {
      const vct: VeryLongOrComplexType = null as any as VeryLongOrComplexType;
      arr.push(vct)
    }
  }
  return arr;
}

arr - can't be infered neither from return type nor from push

In order to do that, you should make arr a variable instead of constant, like here:

interface VeryLongOrComplexType { a: string }
const something: (x: number) => Promise<boolean> = null!
const someList: number[] = null!

async function f(){
  let arr;
  arr = []
  for (const x of someList) {
    if (await something(x)) {
      const vct: VeryLongOrComplexType = null as any as VeryLongOrComplexType;
      arr.push(vct)
      arr // VeryLongOrComplexType[]
    }
  }
  return arr;
}

If you hover on f, you will see that return type is Promise<VeryLongOrComplexType[]>. Just like you expect.

Credits goes to @jcalz.

However, I don't think that you should do such thinkgs in your production code. I still think it is better to explicitly type your empty array, like here:

const arr: VeryLongOrComplexType[] = [];
Sign up to request clarification or add additional context in comments.

6 Comments

There are auto-typed arrays in TypeScript typescriptlang.org/docs/handbook/release-notes/…
Thanks. This can save some keystrokes but it introduces the parameter in function type which isn't really required, and I suspect that may work in some cases but in some others it could make the code less readable. I'll wait to see if there's a better way. I've updated the question with a minimal reproducible example.
@PeeyushKushwaha your exmaple is still not reproducible
@captain-yossarian how do you mean? I've added a screenshot to the question of what I see when I visit the typescript playground link, look at the error underline and the error message on the right
@PeeyushKushwaha my bad, I hsould have refresh a page
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.