4

I define an array of a specific type in typescript. When assigning values that do not correspond to the type, error messages are generated as required. An assignment of the type any works, even if the type is not correct.

Do I misunderstand the type definition of an array? Or do I underestimate the "power" of the anys :-)

Here is a brief example:

export class ItemList {

  items: Array<string> = [];

  constructor() {

    // push a string directly => works
    this.items.push('item 1');

    // push a string variable => works
    let item2:string = 'item 2';
    this.items.push(item2);

    // push a number variable => doesn't work
    let item3 = 3;
    this.items.push(item3);

    // push a number as any type => works
    let item4:any = 4;
    this.items.push(item4);

  }

}

let itemList = new ItemList();

The error from the tsc is:

error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.

Funny thing: the plunkers here works.

Tumen_t
  • 795
  • 5
  • 14
pwunderlich
  • 74
  • 1
  • 2
  • 8
  • You are misunderstanding the purpose of `any`. Quoting the last comment for this [question](http://stackoverflow.com/questions/41749751/typescript-vs-legal-javascript-an-index-must-be-of-type-string-number-sy#comment70698908_41749751): Basically the point of any is that it says "Yes that is OK" to literally any question asked of it by the type system. Can you be assigned from X? Yes. Can you be assigned to Y? Yes. Do you have property Z? Yes. – artem Feb 15 '17 at 20:49
  • Ok, so far is that clear - thx. Any is a multitalent :-) But in the end I do not have the result that I expect. An array in which all elements are of type String. The reason for the question is that I want to make a kind of validation of the data when they come from an external source. – pwunderlich Feb 15 '17 at 21:30
  • Then you have to check it yourself at runtime. There are several ways to bypass constraints imposed by TypeScript type system, even without `any`, [this is one example](https://www.typescriptlang.org/play/#src=let%20items%3A%20Array%20%3C%20string%20%3E%20%3D%20%5B%5D%3B%0D%0A%0D%0Afunction%20f(a%3A%20Array%3C%20%7B%7D%20%3E)%20%7B%0D%0A%20%20%20%20a%5B0%5D%20%3D%202%3B%0D%0A%7D%0D%0A%0D%0Af(items)%3B%0D%0A%0D%0Aconsole.log(typeof%20items%5B0%5D)%3B%20%2F%2F%20number%0D%0A%0D%0A) – artem Feb 15 '17 at 21:48

3 Answers3

16

What you are looking for is union types.

Try this

items: (string|number)[]; // or...
items: Array<string|number>;

Or you can initialize it like this

items: (string|number)[] = ["Hello", 154]; // or...
items: Array<string|number> = ["Hello", 154];
Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
Tumen_t
  • 795
  • 5
  • 14
2

Array of specific type in typescript

export class RegisterFormComponent 
{
     genders = new Array<GenderType>();

     loadGenders()
     {
            this.genders.push({name: "Male",isoCode: 1});
            this.genders.push({name: "FeMale",isoCode: 2});
     }
}

type GenderType = { name: string, isoCode: number };    // Specified format

Array of any type in typescript

export class RegisterFormComponent 
{
     genders = new Array<any>();          
}
Rahul Uttarkar
  • 3,367
  • 3
  • 35
  • 40
0

do I underestimate the "power" of the anys

Yes.

any is assignable to any type, so even though items is string[] and items.push() accepts only string, any is accepted.

But in the end I do not have the result that I expect.

Disallow any then. There are a noImplicitAny rule for tsconfig and no-any and no-unsafe-any rules for tslint.

Still, as seen in @artem's example, since TypeScript does not control co- and contravariance of function parameters, its type system can't guarantee the desired type safety.

Konstantin Pelepelin
  • 1,303
  • 1
  • 14
  • 29