I'm having an issue wherein TypeScript is not exhaustively checking types when the keyof operator is used on types that extend indexable types.

So, the normal use-case of the keyof operator would be something like a Pick<T1, T2> type:

interface Person {
    name: string;
    age: number;
    alive: boolean;

function getPersonInfo<K extends keyof Person>(person: Person, prop: K): Person[K] {
    return person[prop];

getPersonInfo({ name: "John", age: 31, alive: true }, "age"); // compiles and returns 31
getPersonInfo({ name: "John", age: 31, alive: true }, "ssn"); // does NOT compile because "ssn" does not match type of "name" | "age" | "alive"

But when an indexable type is involved, we no longer get this safety of keyof (i.e. a compile-time error telling us that the provided argument is not a key of the type in question). Such as the following:

interface Collection {
    [item: string]: any;

interface MyCollection extends Collection {

    thing: string,
    shmoolean: boolean,
    lumber: number


function getInfo<C extends Collection, K extends keyof C = keyof C>(collection: C, key: K): C[K] {

    return collection[key];


let c: MyCollection = undefined as unknown as MyCollection;

getInfo<MyCollection>(c, "something"); // compiles even though "something" is not a property of MyCollection

Now, I think I understand why this is occurring, and I believe it is due to the fact that on interfaces that extend indexable types, the 'indexable signature' (if you will) is still present on the type, meaning that the type returned by keyof effectively gets widened to string.

So my question is there any way to prevent this from happening? I need to be able to tag classes with their parent indexable type in order to use them in my type system, so I can't just eliminate the indexable type, but I would also like to be able to exhaustively check the type of provided arguments to keyof types and to be given compile-time errors when a non-key is used.