Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript index signature any - only works with `any`?

I have an interface and a class :

export interface State {
    arr : any[];
}


export const INITIAL_STATE: State = {
    arr: []
};

This compiles.

Now I'm chaning the Interface to be like :

export interface State {
    arr : any[];
    [key: string]: any
}

And the class to be like :

export const INITIAL_STATE: State = {
    arr: []    ,
    'a':2
};

- Still compiles.

But now - If I want to be stricter in : [key: string]: any ---> [key: string]: number :

In other words :

export interface State {
    arr : any[];
    [key: string]: number
}


export const INITIAL_STATE: State = {
    arr: []    ,
    'a':2
};

I get an error :

Error:(7, 14) TS2322: Type '{ arr: undefined[]; 'a': number; }' is not assignable to type 'State'. Property 'arr' is incompatible with index signature. Type 'undefined[]' is not assignable to type 'number'.

Question:

Why is that ?
I don't understand the logic behind this restriction. What can I do to resolve it ?

like image 638
Royi Namir Avatar asked Dec 30 '17 10:12

Royi Namir


1 Answers

The following interface:

export interface State {
    arr : any[];
    [key: string]: number
}

gives me the following error without even creating an object:

Property 'arr' of type 'any[]' is not assignable to string index type 'number'

This is because once you define [key: string]: number, TypeScript thinks all properties should be strings that map to a number. So you can't have an array unless you do:

export interface State {
    [key: string]: number | any[]
}

Note that the reason the following interface worked:

export interface State {
    arr : any[];
    [key: string]: any
}

is that [key: string]: any tells TypeScript "map a string to anything", in other words, "turn off type checking for each string property". That is why you can have arr : any[]; without error.

like image 54
Frank Modica Avatar answered Oct 26 '22 12:10

Frank Modica