Home > OS >  Why does key of break when used on generic objects?
Why does key of break when used on generic objects?

Time:07-16

Is it possible to make the types below work? The issue seems to be that T might have symbols. Is there a way to ignore them?

type MyAnimals = { name: "dog", fleas: 2 }
function GetKeys<T extends MyAnimals>(animal: T) {
  type prefixedAnimal = {
    // Type 'key' is not assignable to type 'string | number | bigint | boolean | null | undefined'.
    [key in keyof T as `my${key}`]: T[key]
  }
}

type prefixedAnimal = {
  [key in keyof MyAnimals as `my${key}`]: MyAnimals[key]
}

I tried wrapping my T in an utility type to remove anything except strings, but it didn't fix it:

type OnlyStringKeys<T> = {
  [key in keyof T]: key extends string ? T[key] : never;
}

CodePudding user response:

Yes i think your reasoning is correct. You can filter out any non string keys like this:

type MixedType = "yes" | 0 | "no" | "maybe" | false;
type StringsOnly<T> = T & string;
type Test = StringsOnly<MixedType>; // "yes" | "no" | "maybe"

In your case then:

type MyAnimals = { name: "dog"; fleas: 2 };
function GetKeys<T extends MyAnimals>(animal: T) {
    type prefixedAnimal = {
        // now correctly filters for string keys only
        [key in keyof T & string as `my${key}`]: T[key];
    };
}

Your type does not exclude non string keys:

type MyAnimalsReloaded = { name: "dog"; fleas: 2, 0: number };

// type does not work because it does not exclude the key that is not a string
type test2 = OnlyStringKeys<MyAnimalsReloaded> // has 0: never as a key

Playground

  • Related