Search code examples
typescripttypescript2.8conditional-types

Remove properties of a type from another type


This question is similar, but a bit different from Typescript 2.8: Remove properties in one type from another

I would like to create a function that takes a type, and returns a new type that doesn't include properties that are of type Array or are other complex (nested) objects.

I'm assuming conditional types are the best (only?) way to handle this? How can this be accomplished?


Solution

  • You can create a conditional type that only preserved primitive types (excludes arrays and other objects) using conditional types (to pick out the keys) and Pick

    type PrimitiveKeys<T> = {
        [P in keyof T]: Exclude<T[P], undefined> extends object ? never : P
    }[keyof T];
    type OnlyPrimitives<T> = Pick<T, PrimitiveKeys<T>>
    
    interface Foo {
        n: number;
        s: string;
        arr: number[];
        complex: {
            n: number;
            s: string;
        }
    } 
    
    let d : OnlyPrimitives<Foo> // will be { n: number, s: string }
    

    The actual function implementation should be pretty simple, just iterate the object properties and exclude object

    function onlyPrimitives<T>(obj: T) : OnlyPrimitives<T>{
        let result: any = {};
        for (let prop in obj) {
            if (typeof obj[prop] !== 'object' && typeof obj[prop] !== 'function') {
                result[prop] = obj[prop]
            }
        }
        return result;
    }
    
    let foo = onlyPrimitives({ n: 10, s: "", arr: [] }) ;
    

    Edit Added correct handling for optional fields.