Home > Blockchain >  How to override a generic type's property with an argument's typeof value in typescript
How to override a generic type's property with an argument's typeof value in typescript

Time:05-24

I am trying to create a generic type check function that checks if an object's property has a type. But it would be nice if I didn't need to define the field as both an argument value and type value.

For example, this works but feels a bit redundant:

function isFieldPopulated<T1, T2, K extends keyof T1>(doc: T1, field: K): doc is Omit<T1, K> & Record<K, T2> {
    // check if T1[K] is a T2
    return ...;
}

if (isFieldPopulated<Post, Category, 'category'>(data, 'category')) {
    // data.category is a Category type
}

I was hoping not to have to set 'category' here <Post, Category, 'category'> AND here (data, 'category'). Is there a way for TS to know that the field argument extends keyof T1 without having to specifically put 'category' inside <..., 'category'> since it's already being passed through as a string argument?

UPDATE: Here is a minimal working example.

CodePudding user response:

Because TypeScript can already infer T1 and K correctly for us, there should be no need to explicitly provide T2. It seems that you want only the object types and not primitives (like string), so we can give T2 the type Extract<T1[K], object>, giving us all the object types in T1[K]:

function isFieldPopulated<T1, T2 extends Extract<T1[K], object>, K extends keyof T1>(doc: T1, field: K): doc is T1 & Record<K, T2> {

You can verify that it works here.

  • Related