Search code examples
typescripttype-inferencekeyof

typescript deep keyof when field is an option


I create an function to select and keyof of deep object. but I don't know why this keyof on my object is not work when it is an option.


type Database = {
    User?: {
        id: string
        name: string
    },
    Post?: {   // if i remove ? it work but it should be an option
        id: string
        content: string
    }
}

type SelectQuery<T> = {
    [Table in keyof T]?: {
        select: {
            [field in keyof T[Table]]?: boolean
        }
    }
}


function select(query: SelectQuery<Database>) {}

select({
    Post: {
        select: {
          // it should suggest content and id here

        
        }
    }
})

Playground Link


Solution

  • The problem is that you have nested optional fields in your Database type and when you access one table you get a type tableFields | undefined and keyof returns never for this case. Example:

    // never
    type Case1 = keyof Database['Post']
    

    To fix this issue you can use built-in NonNullable utility type:

    // "id" | "content"
    type Case2 = keyof NonNullable<Database['Post']>
    

    Usage:

    type SelectQuery<T> = {
      [Table in keyof T]?: {
        select: {
          [field in keyof NonNullable<T[Table]>]?: boolean;
        };
      };
    };
    

    playground