Skip to content

Instantly share code, notes, and snippets.

@crutchcorn
Last active November 29, 2021 20:30
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 crutchcorn/00ce31a85d63091936c20b7ebab9c479 to your computer and use it in GitHub Desktop.
Save crutchcorn/00ce31a85d63091936c20b7ebab9c479 to your computer and use it in GitHub Desktop.
// NaN also, but `typeof NaN` === number
type Falsy = false | null | undefined | 0 | -0 | 0n | "";
type AnyArray<T> = Array<T> | ReadonlyArray<T>
type DeepReplaceKeysPartialObj<Obj extends object, T> = {
[key in keyof Obj]:
Obj[key] extends AnyArray<infer Q> ?
DeepReplaceKeys<Q, T> :
Obj[key] extends object ?
DeepReplaceKeys<Obj[key], T> :
T;
};
type DeepReplaceKeys<Obj, T> = Obj extends object ? DeepReplaceKeysPartialObj<Obj, T> : Obj;
type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
type PickDeepObj<ReplaceType, ToPick extends object, PickObj extends DeepPartial<DeepReplaceKeys<ToPick, ReplaceType>>> = {
[key in keyof PickObj]:
key extends keyof ToPick ?
ToPick[key] extends AnyArray<infer Q> ?
Array<PickDeep<ReplaceType, Q, PickObj[key]>> :
ToPick[key] extends object ?
PickDeep<ReplaceType, ToPick[key], PickObj[key]> :
PickObj[key] extends Falsy ?
never :
ToPick[key] :
never
}
type PickDeep<ReplaceType, Obj, T> = Obj extends object ? PickDeepObj<ReplaceType, Obj, T> : Obj;
declare function pickDeep<Obj extends object, ObjDec extends DeepPartial<DeepReplaceKeys<Obj, true | false>>>
(objToPick: Obj, pickObjDeclare: ObjDec): PickDeepObj<true | false, Obj, ObjDec>;
const pickedObject = pickDeep({
test: {
other: 900,
ignored: 9,
explicitNo: 77,
arr: [
{
other: 3000,
ignored: 999
}
]
},
one: 1
} as const, {
test: {
other: true,
arr: {
other: true
},
explicitNo: false
}
} as const);
// No errors
pickedObject['test']['arr'][0]['other']; // Type should be 3000
pickedObject['test']['other']; // Type should be 900
pickedObject['test']['explicitNo']; // type should be "never"
// This should error
pickedObject['test']['arr']['other']
pickedObject['test']['arr'][0]['ignored'];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment