Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursive type with index signature issues spurious error #1889

Closed
NoelAbrahams opened this issue Feb 2, 2015 · 5 comments
Closed

Recursive type with index signature issues spurious error #1889

NoelAbrahams opened this issue Feb 2, 2015 · 5 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@NoelAbrahams
Copy link

Hi,

TS:1.4

The compiler issues an error on property bar below:

   interface Foo {
        [x: string]: number|Foo;
   }

   interface Bar extends Foo {

        /* Error: Property 'bar' of type '{ num: number; }' 
        is not assignable to string index type 'number | Foo'. */
        bar: { num: number };
    }

My understanding of this is "any type that extends Foo is permitted to have a property that is either a number or an object that is indexable by string to produce a number or..(and so on) ".

The latter case is clearly true for {num: number} and yet the compiler issues an error.

@RyanCavanaugh RyanCavanaugh added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Feb 2, 2015
@RyanCavanaugh
Copy link
Member

any type that extends Foo is permitted to have a property that is either a number or an object that is indexable by string to produce a number or..(and so on)

bar is not a number (obviously), but it's also not a Foo because it doesn't have an index signature. The correct declaration looks like this:

interface Foo {
    [x: string]: number|Foo;
}

interface Bar extends Foo {
    // OK
    bar: {
        num: number;
        [x: string]: number|Foo
    };
}

@masaeedu
Copy link
Contributor

@RyanCavanaugh Has an issue related to implicit indexer typing already been opened somewhere? Would be nice to just be able to specify { number|Foo }, since the indexer can't be anything other than string (TS doesn't even care at compile time, you can do let x: { [id: string] number|Foo } = {}; x[5];), and the identifier for the index doesn't seem to be used anywhere.

@RyanCavanaugh
Copy link
Member

The indexing type can also be number. The syntax { number|Foo } isn't an option because the syntax { Foo } already means "an object type with a property number of (implicit) type any).

@masaeedu
Copy link
Contributor

Yes, but it doesn't look like TS actually enforces the type you specify (i.e. let x: { [id: string]: number } = {}; x[5]; and let x: { [id: number]: number } = {}; x["5"]; are both valid). My bad on the suggested syntax. Perhaps { []: number|Foo }?

@RyanCavanaugh
Copy link
Member

Numbers are converted to strings during indexing operations, so it's valid to specify a number as the indexing expression.

The converse is not the case -- if you declare only a number indexer, you can't index by a string without producing an implicit any warning.

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

3 participants