recursion - how to implement typescript deep partial mapped type not breaking array properties -


any ideas how might apply typescript's partial mapped type interface recursively, @ same time not breaking keys array return types?

the following approaches have not been sufficing:

interface user {     emailaddress: string;     verification: {     verified: boolean;     verificationcode: string;   }   activeapps: string[]; }  type partialuser = partial<user>; // not affect properties of verification    type partialuser2 = deeppartial<user>; // breaks activeapps' array return type;  export type deeppartial<t> = {   [ p in keyof t ]?: deeppartial<t[ p ]>; } 

any ideas?

update: accepted answer - better , more general solve now.

had found temporary workaround involves intersection of types , 2 mapped types follows. notable drawback have supply property overrides restore sullied keys, ones array return types.

e.g.

type partialdeep<t> = {   [ p in keyof t ]?: partialdeep<t[ p ]>; } type partialrestorearrays<k> = {   [ p in keyof k ]?: k[ p ]; }  export type deeppartial<t, k> = partialdeep<t> & partialrestorearrays<k>;  interface user {    emailaddress: string;    verification: {    verified: boolean;    verificationcode: string;  }  activeapps: string[]; }  export type adddetailspartialed = deeppartial<user, {  activeapps?: string[]; }> 

like so

okay, here best attempt @ crazy general solution (requiring typescript 2.4 , up) might not worth you, if want use it, guest:

first, need type-level boolean logic:

type false = '0' type true = '1' type bool = false | true type ifelse<cond extends bool, then, else> = {'0': else; '1': then;}[cond]; 

all need know here type ifelse<true,a,b> evaluates a , ifelse<false,a,b> evaluates b.

now define record type rec<k,v,x>, object key k , value type v, rec<k,v,true> means property required, , rec<k,v,false> means property optional:

type rec<k extends string, v, required extends bool> = ifelse<required, record<k, v>, partial<record<k, v>>> 

at point can user , deeppartialuser types. let's describe general userschema<r> every property care either required or optional, depending on whether r true or false:

type userschema<r extends bool> =   rec<'emailaddress', string, r> &   rec<'verification', (     rec<'verified', boolean, r> &     rec<'verificationcode', string, r>   ), r> &   rec<'activeapps', string[], r> 

ugly, right? can describe both user , deeppartialuser as:

interface user extends userschema<true> { } // required interface deeppartialuser extends userschema<false> { }  // optional 

and see in action:

var user: user = {   emailaddress: 'foo@example.com',   verification: {     verified: true,     verificationcode: 'shazam'   },   activeapps: ['netflix','facebook','angrybirds'] } // missing properties or cause error  var deeppartialuser: deeppartialuser = {   emailaddress: 'bar@example.com',   verification: {     verified: false   } } // missing properties fine, still error 

there go. hope helps!


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -