how to create an object based on a type and return for each key just the string value of the...

Discussão em 'Angular' iniciado por T. Jami, Janeiro 7, 2025.

  1. T. Jami

    T. Jami Guest

    Let me explain. I have the following use case: In Angular, I am using a table UI component, which looks kind of the following:

    <my-table [values]="myTableValues">
    <my-column field="firstColumn" />
    </my-table>


    myTableValues has a type for its rows (lets call it myTableValuesRowType) which is generated via a swagger-code generator. As you see, the field takes a string as a value, which makes it less type strict.

    I came up with a solution which creates an object of the type with the same properties and returns the string value of each key. So basically something like this:

    [Key]: KeyString


    This is my code:

    type NonNullableKeys<T> = {
    [K in keyof T]: T[K] extends null | undefined ? never : K;
    }[keyof T];

    export type PropertiesOf<T> = Record<NonNullableKeys<T>, string>;

    export function getTypeProperties<T>(): PropertiesOf<T> {
    return new Proxy({}, {
    get: (_target, prop: string) => prop,
    }) as PropertiesOf<T>;
    }


    Typescript Playground Example

    This makes it easier for us to make the property field in the html template more type strict. It might not be the best solution, but it is the best/easiest solution we could use right now. Example usage:

    //component.ts
    readonly rowProperties = getTypeProperties<myTableValuesRowType>();

    //component.html
    <my-table [values]="myTableValues">
    <my-column [field]="rowProperties.firstColumn" />
    </my-table>


    This way if the generated type changes the property keys I would be able to detect it immediately.

    However there is one main issue, the above function is not recursive. So nested properties are ignored.

    Example:

    type myTableValuesRowType = {
    firstColumn: number;
    secondColumn: string;
    thirdColumn: number[];
    fourthColumn: boolean;
    subrow: {
    firstSubrowColumn: string;
    secondSubrowColumn: number;
    }
    }

    const rowProperties = getTypeProperties<myTableValuesRowType>();

    console.log(rowProperties.firstColumn); //returns "firstColumn"
    console.log(rowProperties.subrow.firstSubrowColumn); //returns undefined & TS-Error: Property 'firstSubrowColumn' does not exist on type 'string'


    Finally my question would be, how can I make it recursive? I tried multiple approaches and did some research in order to find something similar. All I found was to get nested keys in another type, but not really extracting the properties and creating an object of it.

    FYI, I can't change the UI Component Library...

    I would appreciate any help or insights!

    Continue reading...

Compartilhe esta Página