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

Index constraint does not constrain #3150

Closed
dsherret opened this issue May 13, 2015 · 7 comments
Closed

Index constraint does not constrain #3150

dsherret opened this issue May 13, 2015 · 7 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@dsherret
Copy link
Contributor

It seems the index constraint doesn't seem to constrain anymore... if it does, then I blame it being early in the morning.

Copying the code from Ryan's post here:

class Customer {
    dummyProperty: string;
}

var map: { [email: string]: Customer; } = { };
map['foo@gmail.com'] = new Customer(); // OK
map[14] = new Customer(); // Not OK, 14 is not a string -- ACTUALLY, this compiles now
map['bar@hotmail.com'] = 'x'; // Not OK, x is not a customer

Playground

Apologies if this has already been raised, but I couldn't find a duplicate issue. Maybe this is now by design?

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

We changed the behavior here because (at runtime) numbers are implicitly converted to strings during index operations. Basically, a string indexer is a "superset" of a number indexer.

@dsherret
Copy link
Contributor Author

@RyanCavanaugh ok, thanks! That's slightly annoying though... from what I see that change makes defining the type on an index useless. In my opinion, the runtime behaviour should not be taken into consideration when someone explicitly defines the index type. If someone wanted the current behaviour, I think it would make more sense for them to write:

var map: { [email: string | number]: Customer; } = { };

Oh well :(

@arusland
Copy link

@RyanCavanaugh could you explain why second assignment is incorrect?

interface SomeArray1 {
    [index: number]: string;    
}

var my1: SomeArray1;
my1["12"] = 12;
my1[12] = 12; // <-- why this line is incorrect but first assignment before is OK?

I think it's a violation of POLA principle

@RyanCavanaugh
Copy link
Member

We don't treat numeric-looking string literals as numbers, for obvious reasons, so this is the same as writing my1['foo'] which a lot of people like to do to work around the type system. This is basically an escape hatch for when you don't want the type system involved.

This is implemented via the global type Object [effectively] having a string indexer that returns any, but using this implicit indexer is an error under --noImplicitAny.

@zjiekai
Copy link

zjiekai commented Oct 10, 2016

@RyanCavanaugh

a string indexer is a "superset" of a number indexer.

I'm wondering why the following code compiles.

class Customer {
    dummyProperty: string;
}

var map: { [key: number]: Customer; } = {};

map[14] = new Customer();
map['map'] = new Customer();  // <-- Why does this line compile?

Playground

Update: It seems it's a problem of the playground. My local tsc raises TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.

@dsherret
Copy link
Contributor Author

@zjiekai that's because the playground doesn't compile with the --noImplicitAny compiler flag.

@RyanCavanaugh
Copy link
Member

FYI please don't drop questions into old issues - ask them on Stack Overflow. If you think you've found a bug, log a new issue.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 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

4 participants