Talgat Saribayev
Talgat Saribayev

Reputation: 1938

Typescript generics and keyof

I have issues with keyof and generics. Have two objects: one argument Config, second result MyFilter. MyFilter should be created with keys of Config. Please help:

enum Type {
  Boolean,
  Number,
  String,
}

// f.e. { name: Type.String, age: Type.Number }
interface Config {
  [key: string]: Type;
}

// should have the same keys as Config and corresponding types, f.e. { name: "Expecto Patronum!", age: 43 }
type MyFilter<C extends Config> = {
  [Key in keyof C]: C[Key] extends Type.Boolean
    ? boolean
    : C[Key] extends Type.Number
    ? number | null
    : C[Key] extends Type.String
    ? string | null
    : undefined;
};

// C and F should have same keys, but how to create F var and iterate over C to fill F with keyof
function createFilter<C extends Config = Config, F extends MyFilter<C> = MyFilter<C>>(config: C): F {
    const filter = {}

    // DO loop
    switch (config[key]) {
        case Type.Boolean:
            filter[key] = true
        case Type.Number:
            filter[key] = 43
        case Type.String:
            filter[key] = "Expecto Patronum!"
    }
    // END loop

    return filter
}

Playground Example

Upvotes: 0

Views: 75

Answers (1)

Cody Duong
Cody Duong

Reputation: 2482

It is not necessary for filter to be a generic. Then using the for...in you can iterate over the object. Then utilize type casting with the as operator to assert the type.

function createFilter<C extends Config = Config>(config: C): MyFilter<C> {
    const filter: Record<string, any> = {}

    // DO loop
    for (const key in config) {
      switch (config[key]) {
        case Type.Boolean:
            filter[key] = true
        case Type.Number:
            filter[key] = 43
        case Type.String:
            filter[key] = "Expecto Patronum!"
    }
    }
    // END loop

    return filter as MyFilter<C>
}

TS Playground Link

Upvotes: 2

Related Questions