0

In the following code, TypeScript seems to flippantly decide when a type is indexable by a string:

type Model = { [k: string]: any };

export class MyClass<TModel extends Model> {

    get(target: TModel, key: string) {
        return target[key];  //passes
    }

    set(target: TModel, key: string, value: any) {
        target[key] = value; //ts(2536) Type 'string' cannot be used to index type 'TModel'
    } 

}

TypeScript version: 4.7.2.

I've been bumping into this issue a lot lately and I'm wondering if anyone knows why.

1 Answer 1

1

Not sure of the exact explanation of why that doesn't work -- but I can fix the problem for you:

Type your "key" arguments as keyof TModel rather than string. E.g.:

set(target: TModel, key: keyof TModel, value: any) {

Perhaps because TModel extends Model, the checker thinks there could be a non-string prop key that would be referenced by a string.

Another solution might be to simply remove the generic parameter and type the target arguments as Model. You're not really using that generic type anyway. Anything that extends Model will still be accepted as those first arguments.

This code compiles fine with either approach:

const sym = Symbol("whatevs");
const my = new MyClass();
const model = { some: "thing", [sym]: "what?" };
my.set(model, "some", "other thing");
Sign up to request clarification or add additional context in comments.

3 Comments

It works to fix that single case, but the key needs to be re-usable with different objects. Sometimes their type isn't defined so this becomes complicated. It seems like the ideal would be to define the type as indexable by string.
You might not need the generic parameter in this case -- just added to my answer.
Either approach i've suggested here should work in all cases.

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.