Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
780 views
in Technique[技术] by (71.8m points)

recursion - How to implement TypeScript deep partial mapped type not breaking array properties

Any ideas as to how might apply TypeScript's Partial mapped type to an interface recursively, at the same time not breaking any keys with 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>; // does 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 - A better and more general solve for now.

Had found a temporary workaround which involves intersection of types and two mapped types as follows. The most notable drawback is that you have to supply the property overrides to restore sullied keys, the ones with 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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

With TS 2.8 and conditional types we can simply write:

type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends Array<infer U>
    ? Array<DeepPartial<U>>
    : T[P] extends ReadonlyArray<infer U>
      ? ReadonlyArray<DeepPartial<U>>
      : DeepPartial<T[P]>
};

or with [] instead of Array<> that would be:

type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends (infer U)[]
    ? DeepPartial<U>[]
    : T[P] extends Readonly<infer U>[]
      ? Readonly<DeepPartial<U>>[]
      : DeepPartial<T[P]>
};

You might want to checkout https://github.com/krzkaczor/ts-essentials package for this and some other useful types.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...