Skip to content

Instantly share code, notes, and snippets.

@justsanjit
Created April 19, 2023 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justsanjit/21dc05e9ba00af4f7218439f687be034 to your computer and use it in GitHub Desktop.
Save justsanjit/21dc05e9ba00af4f7218439f687be034 to your computer and use it in GitHub Desktop.
Typescript mapped type that will accept a nested object and a list of paths to make required.
interface Phone {
number: string
extension?: string
}
interface Person {
firstName?: string;
lastName?: string;
age?: number;
address?: {
street?: string;
city?: string;
zip?: number;
},
phones?: Phone[]
}
type Expand<T> = T extends ReadonlyArray<unknown> ? Expand<T[number]>[] : T extends object ? { [K in keyof T]: Expand<T[K]> } : T;
type TopLevelPath<T extends string> = T extends `${infer U}.${infer _}` ? U : T;
type PathsToTopLevel<T extends ReadonlyArray<string>> = {
[K in keyof T]: TopLevelPath<T[K]>;
};
type RemoveTopLevelPath<T extends ReadonlyArray<string>> = {
[K in keyof T]: T[K] extends `${infer _}.${infer V}` ? V : never;
};
type OmitProperties<T, K extends ReadonlyArray<string>> = {
[P in keyof T as P extends K ? never : P]: T[P];
};
type RecursiveRequired<T, K extends ReadonlyArray<string>> = Omit<T, PathsToTopLevel<K>[number]> & {
[P in PathsToTopLevel<K>[number]] : T[P & keyof T] extends Array<infer U>
? RecursiveRequired<U, RemoveTopLevelPath<K>>[]
: T[P & keyof T] extends string
? string
: T[P & keyof T] extends Object
? RecursiveRequired<T[P & keyof T], RemoveTopLevelPath<K>>
: T[P & keyof T]
}
type PersonWithRequiredFields = Expand<RecursiveRequired<Person, ['firstName', 'phones', 'phones.extension', 'age']>>
// const p: PersonWithRequiredFields = {
// firstName: 'Sanjit'; // Required
// lastName: string; // Optional
// age: number; // Optional
// address?: { // Optional
// street?: string; // Optional
// city?: string; // Optional
// zip?: number; // Optional
// },
// phones: { // Required
// number: '123456789' // Optional
// extension: '123' // Required
// }
// }
@justsanjit
Copy link
Author

I am not pro in typescript. Any suggestions to improve this code will be appreciated.

@justsanjit
Copy link
Author

justsanjit commented Apr 19, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment