Typescript: BUG: Array with string type elements

Created on 18 Feb 2019  路  6Comments  路  Source: microsoft/TypeScript

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?

Unactionable

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 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.

All 6 comments

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));

play link

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rbuckton picture rbuckton  路  139Comments

born2net picture born2net  路  150Comments

metaweta picture metaweta  路  140Comments

rwyborn picture rwyborn  路  210Comments

fdecampredon picture fdecampredon  路  358Comments