UNPKG

typedots

Version:

A simple way to get and set object properties using paths (aka dot notation) with TypeScript support

67 lines (56 loc) 4.38 kB
type PathParams<T, Rest> = { first: T; rest: Rest; }; type AnyObject = Record<string, unknown>; type AcceptNullable<T> = Exclude<T, null | undefined>; type SanitizeKey<Key, DoSanitize extends boolean> = DoSanitize extends true ? Key extends `${string}.${string}` ? `(${Key})` : Key & string : Key; type Join<Prefix extends string = '', Key extends string = '', DoSanitize extends boolean = true> = `${Prefix}${SanitizeKey<Key, DoSanitize>}`; type Matcher<Type, KeyPath extends string, ExpectedType, PreventDistribution extends boolean> = PreventDistribution extends true ? [Type] extends [ExpectedType] ? KeyPath : never : Type extends ExpectedType ? KeyPath : never; /** * @example ```ts * type Input = { one: { subone: { subonetwo: string; } } }; * * type OutputOne = AddProp<Input, 'one.subone.subonethree', number>; * declare const outputOne: OutputOne; * outputOne.one.subone.subonethree = 5; * * type OutputTwo = AddProp<Input, 'two', string>; * declare const outputTwo: OutputTwo; * outputTwo.two = 'str'; * ``` */ type AddProp<T extends AnyObject, Path extends string, TargetType, Params extends PathParams<any, any> = Split<Path>> = T & Record<Params['first'], Params['rest'] extends undefined ? TargetType : T[Params['first']] extends AnyObject ? Params['rest'] extends `(${infer A})` ? T[Params['first']] & Record<A, TargetType> : AddProp<T[Params['first']], Params['rest'], TargetType> : Record<Params['rest'], TargetType>>; type Split<T extends string> = (T extends `(${infer A}).${infer Rest}` ? PathParams<A, Rest> : T extends `${infer A}.${infer Rest}` ? PathParams<A, Rest> : PathParams<T, undefined>); type ObjectPaths<T, ExpectedType, PreventDistribution extends boolean, Prefix extends string = ""> = T extends never ? never : { [K in keyof T & string]: AcceptNullable<T[K]> extends AnyObject ? Matcher<T[K], Join<Prefix, K>, ExpectedType, PreventDistribution> | ObjectPaths<AcceptNullable<T[K]>, ExpectedType, PreventDistribution, `${Join<Prefix, K>}.`> : Matcher<T[K], Join<Prefix, K>, ExpectedType, PreventDistribution>; }[keyof T & string]; type ExtractObjectPaths<T, ExpectedType = DefaultTypedotsParams['expectedType'], PreventDistribution extends boolean = DefaultTypedotsParams['preventDistribution']> = ObjectPaths<T, ExpectedType, PreventDistribution>; type GetMethod<P extends TypedotsParams = DefaultTypedotsParams> = <BaseObject extends AnyObject, Path extends ExtractObjectPaths<BaseObject, P['expectedType'], P['preventDistribution']>>(object: BaseObject, path: Path) => undefined | any; type UpdateApplied = boolean; type HasMethod<P extends TypedotsParams = DefaultTypedotsParams> = <BaseObject extends AnyObject, Path extends ExtractObjectPaths<BaseObject, P['expectedType'], P['preventDistribution']>>(object: BaseObject, path: Path) => boolean; declare const get: GetMethod; declare const set: <BaseObject extends AnyObject, Path extends Force extends true ? ExtractObjectPaths<BaseObject, any, true> | string : ExtractObjectPaths<BaseObject, any, true>, Value, Force extends boolean = false>(object: BaseObject, path: Path, value: Value, force?: Force) => object is Force extends true ? Prettify<AddProp<BaseObject, Path, typeof value>> : BaseObject; type Prettify<T> = { [K in keyof T]: T[K]; } & {}; declare const has: HasMethod; interface TypedotsParams { expectedType?: any; preventDistribution: boolean; } type DefaultTypedotsParams = TypedotsParams & { expectedType: any; preventDistribution: false; }; declare class BaseTypedots<P extends TypedotsParams> { get: GetMethod<P>; set: typeof set; has: HasMethod<P>; } declare class Typedots<P extends TypedotsParams> implements BaseTypedots<P> { get: GetMethod<P>; set: <BaseObject extends AnyObject, Path extends Force extends true ? ExtractObjectPaths<BaseObject, any, true> | string : ExtractObjectPaths<BaseObject, any, true>, Value, Force extends boolean = false>(object: BaseObject, path: Path, value: Value, force?: Force) => object is Force extends true ? AddProp<BaseObject, Path, Value> extends infer T ? { [K in keyof T]: AddProp<BaseObject, Path, Value>[K]; } : never : BaseObject; has: HasMethod<P>; } export { BaseTypedots, type DefaultTypedotsParams, type ExtractObjectPaths, type GetMethod, type HasMethod, type TypedotsParams, type UpdateApplied, Typedots as default, get, has, set };