54

I'd like to access typed object with bracket notation like this:

interface IFoo {
    bar: string[];
}

var obj: IFoo = { bar: ["a", "b"] }
var name = "bar";
obj[name]. // type info lost after dot 

According to the spec 4.10 as far as I understood it, it is an expected behavior:

A bracket notation property access of the form ObjExpr [ IndexExpr ]  
....  
Otherwise, if IndexExpr is of type Any, the String or Number primitive type, or an enum type, the property access is of type Any.

Can anyone confirm if that is true and if it is possible to circumvent this behavior.

Edit: My use case is with object minification as in

var props = {long_name: "n"};    
var shortName = props.long_name;

function(minObj) {
    var value = minObj[shortName]
    var newMinObj = {};
    newMinObj[shortName] = value.toUpperCase();
    db.save(newMinObj)
}

2 Answers 2

53

I added it as a separate interface because i need to keep original..

export interface IIndexable {
  [key: string]: any;
}

and referencing it when needed

getEditDate(r: IRestriction, fieldName: string) {
    ...
    value={(r as IIndexable)[fieldName] as Date}

works well. i will update if i find a way to shorten it

Sign up to request clarification or add additional context in comments.

1 Comment

Great! I made it generic to keep type safety: export interface IIndexable<T = any> { [key: string]: T }
38

Instead of using a variable in obj[x], you can write:

obj["bar"].sort

The only reason to use a variable here is to choose an arbitrary property from your IFoo interface. You seem to only have one. If you had many string arrays on your IFoo, you could make it indexable and write:

interface IFoo {
    bar: string[];
    bar2: string[];
    [key: string]: string[]; // IFoo is indexable; not a new property
}

Which would allow you to write:

var name = "bar";
obj[name].sort;

But it would also allow you to write:

obj["some new property"] = ["a", "b"];
obj["some new property"].sort;

5 Comments

but it won't work if IFoo has properties of different types, right?
sorry to bother you even more but I've updated original question with a potential use case. it seems that there is no generic method to let typescript know that shortName is and always going to be a string "n".
That would be a fairly complicated inference (and in most cases it would not work, in others, it would not be useful). TypeScript does not perform it. Often, an inability or difficulty in doing things a certain way in a language suggests that that is a bad way to do things in that language (at least because people would be unfamiliar with it, though often it is actually unsuitable and a bad idea).
If you want to have different types you can make use of union. In that example you would define your index as following [key: string]: string[] | your_second_type;
Figuring out to make the type for the key generic this guide really helped, to show how to use keyof

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.