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

String enum can't be used to index into an object #16760

Closed
zakjan opened this issue Jun 27, 2017 · 6 comments
Closed

String enum can't be used to index into an object #16760

zakjan opened this issue Jun 27, 2017 · 6 comments
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@zakjan
Copy link

zakjan commented Jun 27, 2017

TypeScript Version: 2.4.0

Code

enum Name {
    A = "a",
    B = "b",
    C = "c",
}

// interfaces with computed property names are not supported yet, see https://github.com/Microsoft/TypeScript/issues/5579
interface Item {
    /* [Name.A] */ a: string;
    /* [Name.B] */ b: number;
    /* [Name.C] */ c: boolean;
}

const names: Name[] = [Name.A, Name.B, Name.C];

const item: Item = {
    [Name.A]: "a",
    [Name.B]: 1,
    [Name.C]: true,
};

names.forEach((name: Name) => {
    console.log(item[name]);
});

Expected behavior:
No errors are thrown (ideally also when using the commented code with computed interface property names).

Actual behavior:

src/test.ts(16,7): error TS2322: Type '{ [x: string]: string | number | boolean; }' is not assignable to type 'Item'.
  Property 'a' is missing in type '{ [x: string]: string | number | boolean; }'.
src/test.ts(23,17): error TS7017: Element implicitly has an 'any' type because type 'Item' has no index signature.
@zakjan
Copy link
Author

zakjan commented Jun 27, 2017

The first error is duplicate of #16687, the second error is new.

@Jessidhia
Copy link

I'm not sure if there's a way around the second one other than asserting as keyof typeof item. However, it should work if Name is used for a mapped type definition, or when it's used in a computed key once #5579 works.

@ciekawy
Copy link

ciekawy commented Aug 18, 2017

just to jump in with related question, what about

enum Name {
  A = 'a',
  B = 'b'
};

const item: Item = {
  [name: Name]: string; 
};

gives an error

Error:(6, 38) TS1023:An index signature parameter type must be 'string' or 'number'.

could it be possible to use the above approach to expect the property names to use only values defined in an enum Name

@mhegazy
Copy link
Contributor

mhegazy commented Aug 18, 2017

We do handle union types specially in indexing, we should probably do the same for string enums, since they are strictly a union of string literals (and possibly for all union enums).
I would say the change should be as simple as adding a clause to the if statement in getIndexedAccessType.

@mhegazy mhegazy added the Bug A bug in TypeScript label Aug 18, 2017
@mhegazy mhegazy added this to the TypeScript 2.6 milestone Aug 18, 2017
@sandersn sandersn added this to In Progress in Rolling Work Tracking Aug 24, 2017
@sandersn sandersn changed the title Errors when using string enums as property names String enum can't be used to index into an object Aug 24, 2017
@sandersn
Copy link
Member

Given that #16687 already tracks the first part of this, let's use this bug to track the last part, the use of a string enum to index into an object type that has the same keys. Here's a cut-down repro:

// @noImplicitAny: true
enum Name {
    A = "a",
    B = "b",
    C = "c",
}

interface Item {
    a: string;
    b: number;
    c: boolean;
}

declare const item: Item;
declare const name: Name;
let result = item[name];

@sandersn
Copy link
Member

Fix is up at #18029

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

5 participants