Search code examples
typescripttypescript-partial

How to make a Pick property Partial


I have this function

function someThing(someArg: Pick<HTMLElement, 'id' | 'style'>) {...}

However, I only want to add some styles to someArg.style, not all the style from CSSStyleDeclaration. Otherwise, the input of the function will be huge.

So I expect to have something like Pick from Partial<CSSStyleDeclaration> not Pick from CSSStyleDeclaration

How can I do that?


Solution

  • Since your type is more complicated than just Picking some properties from an existing type, you might want to spell it out in its own interface:

    interface SomeArg {
      id: HTMLElement['id'],
      style: Partial<HTMLElement['style']>
    }
    
    function someThing(someArg: SomeArg) { }
    
    someThing({id: "id", style: {
      zIndex: "1"
    }})
    

    I'm using lookup types to make it clear that the id and style properties are related to those from HTMLElement, but you could use just string and Partial<CSSStyleDeclaration> instead.

    If you really need to use something like Pick that allows subproperties to be Partial you can make a mapped type to do it, but I can't tell from your question if you need something programmatic.

    UPDATE

    I guess you do want it to be programmatic (although for just two properties I wouldn't bother, myself) so here's a way to define PickPartial so that you are picking from Partial properties instead of the properties themselves. I assume you don't need it to be recursive (you don't need each of the subproperties to themselves be Partial):

    type PickPartial<T, K extends keyof T> = {[P in K]: Partial<T[P]>};
    
    function someThing(someArg: PickPartial<HTMLElement, 'id'|'style'>) { }
    someThing({id: "1", style: {
      zIndex: "1"
    }})
    

    Note that while this technically makes id the type Partial<string>, that is fine because mapped types do not modify primitives.. Partial<string> is just string. So the type of someArg is the same as the SomeArg interface I spelled out above.


    Hope that helps. Good luck!