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

Inconsistency in inferring string indexers #29423

Closed
sunyatasattva opened this issue Jan 15, 2019 · 6 comments
Closed

Inconsistency in inferring string indexers #29423

sunyatasattva opened this issue Jan 15, 2019 · 6 comments
Labels
Duplicate An existing issue was already created

Comments

@sunyatasattva
Copy link

sunyatasattva commented Jan 15, 2019

TypeScript Version: 3.2.2
Search Terms: String index

Code

interface TestInterface {
  movX: number,
  movY: number
}

let str: "X" | "Y" = "Y";
const testObject: TestInterface = {
  movX: 0,
  movY: 0
};

testObject[`mov${str}`] *= 33;
testObject['movX'] *= 34;

Expected behavior:
TypeScript correctly recognizes that testObject[`mov${str}`] can only be type: number because str can only be type: "X" | "Y".

Actual behavior:
Typescript complains:

Element implicitly has an 'any' type because type 'TestInterface' has no index signature.

Playground Link:
http://www.typescriptlang.org/play/#src=interface%20TestInterface%20%7B%0D%0A%20%20movX%3A%20number%2C%0D%0A%20%20movY%3A%20number%0D%0A%7D%0D%0A%0D%0Alet%20str%3A%20%22X%22%20%7C%20%22Y%22%20%3D%20%22Y%22%3B%0D%0Aconst%20testObject%3A%20TestInterface%20%3D%20%7B%0D%0A%20%20movX%3A%200%2C%0D%0A%20%20movY%3A%200%0D%0A%7D%3B%0D%0A%0D%0AtestObject%5B%60mov%24%7Bstr%7D%60%5D%20*%3D%2033%3B%0D%0AtestObject%5B'movX'%5D%20*%3D%2034%3B

Also, this is just a short example, I don't want to declare a string indexer, because my real-world object is more complex than the one shown in the example.

@AnyhowStep
Copy link
Contributor

AnyhowStep commented Jan 15, 2019

Yikes. As far as I know, TS doesn't do compile-time string interpolation.

This is more a feature request than a bug report.

To TS, `mov${str}` can only ever be of type string. Would be pretty interesting to have compile-time string interpolation and resolving to string literal types.

@RyanCavanaugh
Copy link
Member

Duplicate of #14584

@RyanCavanaugh RyanCavanaugh marked this as a duplicate of #14584 Jan 15, 2019
@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jan 15, 2019
@sunyatasattva
Copy link
Author

Thank you both @RyanCavanaugh and @AnyhowStep for the reply. Both #14584, and #13969 referenced within, have not been updated in close to two years. What's the official stance on this request? This seems to be to be consistent with the way TS currently works.

Is there any workaround, to avoid having TS complain about this issue?

@milesj
Copy link

milesj commented Jan 16, 2019

Does this work?

testObject[str === 'X' ? 'movX' : 'movY'] *= 33;

If not, you can probably force the key.

testObject[(str === 'X' ? 'movX' : 'movY') as keyof TestInterface] *= 33;

@sunyatasattva
Copy link
Author

Thanks for the suggestion, I tried the following, and it works:

const key = `mov${str}` as keyof TestInterface;

testObject[key] *= 33;

…except that it doesn't, really. The above was a simplified example, as soon as TestInterface is more complicated, this doesn't really achieve its intended result.

interface TestInterface {
  movX: number,
  movY: number,
  anExtraKey: string
}

const key = `mov${str}` as keyof TestInterface; // is now "movX" | "movY" | "anExtraKey"

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants