TypeScript Version: 3.3.3
Code
function arrayToString(arr: Array<string>):string {
arr.forEach((item) => {
console.log('typeof item',typeof item, item);
})
return arr.join("\n");
}
function forwardParams(...args){
console.log('typeof args', typeof args, args);
return arrayToString(args);
}
const sampleArr = [
'foo',
'bar',
{
foo: 'bar',
bar: 'foo'
}
];
console.log(forwardParams(...sampleArr));
Expected behavior:
arrayToString method throws a TypeError
Actual behavior:
arrayToString method eats the Object array item
Is it a bug or a feature?
forwardParams has an untyped parameter args. If no type is specified it will implicitly be any. Any can be assigned to anything and can be assigned from anything.
Give this, when you call forwardParams you can pass in anything (since args is of type any). Inside forwardParams you can call arrayToString(args) again since args is of type any.
You should generally specify argument types to help the compiler check you code. This will raise a compilation error:
function arrayToString(arr: Array<string>):string {
arr.forEach((item) => {
console.log('typeof item',typeof item, item);
})
return arr.join("\n");
}
function forwardParams(...args: string[]){
console.log('typeof args', typeof args, args);
return arrayToString(args);
}
const sampleArr = [
'foo',
'bar',
{
foo: 'bar',
bar: 'foo'
}
];
console.log(forwardParams(...sampleArr));
There is also a compiler option to force you to specify types of an apropriate type can't be inferred from context, the option is noImplictAny docs
i can agree this, and it's a nice workaround, the forwardParams can checks the ...args, but the main problem is the same. Without that the object will pass through.
@profhun
I am not sure what part you expect would raise an error. As your code is written it works as intended. The omission of the argument type creates a hole in type checking, but this is by design to allow gradual typing of a code base. If you want this code to raise a typescript error you need to use noImplicitAny and then use an explicit type annotation (preferably one that does not contain any ie not forwardParams(...args: any[])
If you are expecting a runtime error, that is out of scope for Typescript.
It's unclear if this is a question, bug report, or suggestion, or what you're proposing/specifically citing in any case.
it's a bug.
i try to explain in a simple way:
you have this function:
function arrayToString(arr: Array<string>):string
the expected behavior is:
drop a typeError when the array has any value is not a string
actual behavior:
it not drops.
Thank you...
p.s.:
that one line matters, the other ones is only the decoration.
@profhun When are you expecting this type error ? At compile time ? At runtime ?
If you are expecting it at compile time, then you do get an error, as long as you don't leave out a type (which you can make an error with noImplicitAny) or don't type something explicitly as any
If you are expecting an error at runtime, then this is not something typescript was designed to do. Typescript does no runtime checking on anything, only static checking when compiling the ts code. The generated JS looses all type information as behaves as any JS code would.
There are multiple ways to get around the type system and call arrayToString with something that is not an array of string, you found one, calling with an implicitly typed array of any, another would be to call directly from JS code.
This is working as intended, under the current design.
Most helpful comment
@profhun When are you expecting this type error ? At compile time ? At runtime ?
If you are expecting it at compile time, then you do get an error, as long as you don't leave out a type (which you can make an error with
noImplicitAny) or don't type something explicitly asanyIf you are expecting an error at runtime, then this is not something typescript was designed to do. Typescript does no runtime checking on anything, only static checking when compiling the ts code. The generated JS looses all type information as behaves as any JS code would.
There are multiple ways to get around the type system and call
arrayToStringwith something that is not an array ofstring, you found one, calling with an implicitly typed array ofany, another would be to call directly from JS code.This is working as intended, under the current design.