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[] = [];
noImplicitAnyconfiguration and apart from that maybe everything else is fine. I still don't understand what's happening.