Skip to content

Commit

Permalink
update(assoc) Simplify Typings to fix inference and cross function us…
Browse files Browse the repository at this point in the history
…age (#100)
  • Loading branch information
Harris-Miller authored Mar 2, 2024
1 parent 1595fed commit 6027164
Showing 1 changed file with 33 additions and 69 deletions.
102 changes: 33 additions & 69 deletions types/assoc.d.ts
Original file line number Diff line number Diff line change
@@ -1,97 +1,61 @@
import { Placeholder } from './util/tools';

// assoc(prop)
export function assoc<K extends string>(prop: K): {
// assoc(prop)(val)
export function assoc<K extends PropertyKey>(prop: K): {
// assoc(prop)(val)(obj)
<T>(val: T): {
// assoc(prop)(val)(obj) when obj has key prop and val is typeof obj[prop]
<U extends Record<K, T>>(obj: U): U;
// assoc(prop)(val)(obj) when obj has key prop and val is not typeof obj[prop]
<U extends Record<K, any>>(obj: U): Record<K, T> & Omit<U, K>;
// assoc(prop)(val)(obj) when obj does not have key prop
<U>(obj: U): U & Record<K, T>;
<U>(obj: U): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
}

// assoc(prop)(__, obj) when prop is keyof obj
<U extends Record<K, any>>(__: Placeholder, obj: U): {
// assoc(prop)(__, obj)(val) if val is typeof obj[prop]
<T extends U[K]>(val: T): U;
// assoc(prop)(__, obj)(val) if val is not typeof obj[prop]
<T>(val: T): Record<K, T> & Omit<U, K>;
// assoc(prop)(__, obj)(val)
<U>(__: Placeholder, obj: U): {
<T>(val: T): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
}
// assoc(prop)(__, obj) when prop is not keyof obj
<U>(__: Placeholder, obj: U): <T>(val: T) => U & Record<K, T>;

// assoc(prop)(val, obj) when obj has key prop, tests if val is typeof obj[prop] for best return type
<T, U extends Record<K, any>>(val: T, obj: U): U[K] extends T ? U : Record<K, T> & Omit<U, K>;
// assoc(prop)(val, obj) when obj does not have a key prop
<T, U>(val: T, obj: U): U & Record<K, T>;
// assoc(prop)(val, obj)
<T, U>(val: T, obj: U): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
};

// assoc(__, val)
export function assoc<T>(__: Placeholder, val: T) : {
// assoc(__, val)(prop)
<K extends string>(prop: K): {
// assoc(__, val)(prop)(obj) when obj has key prop, tests if val is typeof obj[prop] for best return type
<U extends Record<K, any>>(obj: U): U[K] extends T ? U : Record<K, T> & Omit<U, K>;
// assoc(__, val)(prop)(obj) when obj does not have key prop
<U>(obj: U): U & Record<K, T>;
// assoc(__, val)(prop)(obj)
<K extends PropertyKey>(prop: K): {
<U>(obj: U): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
}

// assoc(__, val)(__, obj)
// assoc(__, val)(__, obj)(prop)
<U>(__2: Placeholder, obj: U): {
// assoc(__, val)(__, obj)(prop), prop is keyof obj, tests if val is typeof obj[prop] for best return type
<K extends keyof U>(prop: K): U[K] extends T ? U : Record<K, T> & Omit<U, K>;
// assoc(__, val)(__, obj)(prop), prop is not keyof obj
<K extends string>(prop: K): U & Record<K, T>;
<K extends PropertyKey>(prop: K): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
};
// assoc(__, val)(prop, obj), when obj has key prop, tests if val is typeof obj[prop] for best return type
<K extends keyof U, U>(prop: K, obj: U): U[K] extends T ? U : Record<K, T> & Omit<U, K>;
// assoc(__, val)(prop, obj), when obj does not have key prop
<K extends string, U>(prop: K, obj: U): U & Record<K, T>;

// assoc(__, val)(prop, obj)
<K extends PropertyKey, U>(prop: K, obj: U): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
};

// assoc(prop, val)
export function assoc<T, K extends string>(prop: K, val: T) : {
// assoc(prop, val)(obj), when obj has key prop, tests if val is typeof obj[prop] for best return type
<U extends Record<K, any>>(obj: U): U[K] extends T ? U : Record<K, T> & Omit<U, K>;
// assoc(prop, val)(obj), when obj does not have key prop
<U>(obj: U): U & Record<K, T>;
// assoc(prop, val)(obj)
export function assoc<T, K extends PropertyKey>(prop: K, val: T): {
<U>(obj: U): U extends Record<K, any> ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
};

// assoc(__, __, obj)
export function assoc<U>(__: Placeholder, __2: Placeholder, obj: U): {
// assoc(__, __, obj)(key)
<K extends keyof U>(key: K): {
// assoc(__, __, obj)(key)(value), when K is keyof U and value types match
<T extends U[K]>(val: T): U;
// assoc(__, __, obj)(key)(value), when K is keyof U and value types do not match
<T>(val: T): Record<K, T> & Omit<U, K>
// assoc(__, __, obj)(key)(val)
<K extends PropertyKey>(key: K): {
<T>(val: T): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
}
// assoc(__, __, obj)(key)(value), when K is not keyof U
<K extends string>(key: K): <T>(val: T) => U & Record<K, T>;
// assoc(__, __, obj)(__, value)
// assoc(__, __, obj)(__, value)(key)
<T>(__: Placeholder, val: T): {
// assoc(__, __, obj)(__, value)(key), when obj has key prop, tests if val is typeof obj[prop] for best return type
<K extends keyof U>(key: K): U[K] extends T ? U : Record<K, T> & Omit<U, K>;
// assoc(__, __, obj)(__, value)(key) when obj does not have key prop
<K extends string>(key: K): U & Record<K, T>;
<K extends PropertyKey>(key: K): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
}
// assoc(__, __, obj)(key, value)
<K extends keyof U>(key: K, val: U[K]): U;
<K extends keyof U, T>(key: K, val: T): Record<K, T> & Omit<U, K>;
<K extends string, T>(key: K, val: T): U & Record<K, T>;
<K extends PropertyKey, T>(key: K, val: T): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
};

// assoc(__, val, obj)(prop), this tests if prop is keyof obj and if val is typeof obj[prop] for best return type
export function assoc<T, U>(__: Placeholder, val: T, obj: U): <K extends string>(prop: K) => K extends keyof U ? T extends U[K] ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;
// assoc(prop, __, obj)(val), when K is keyof obj, tests if val is typeof obj[prop] for best return type
export function assoc<U, K extends keyof U>(prop: K, __: Placeholder, obj: U): <T>(val: T) => T extends U[K] ? U : Record<K, T> & Omit<U, K>;
// assoc(prop, __, obj)(val), when prop is not keyof obj
export function assoc<U, K extends string>(prop: K, __: Placeholder, obj: U): <T>(val: T) => U & Record<K, T>;
// assoc(prop, val, obj) when prop is keyof obj and val is same type
export function assoc<K extends keyof U, U>(prop: K, val: U[K], obj: U): U;
// assoc(prop, val, obj) when prop is keyof obj and val is not same type
export function assoc<T, K extends keyof U, U>(prop: K, val: T, obj: U): Record<K, T> & Omit<U, K>;
// assoc(prop, val, obj) when prop is not keyof obj
export function assoc<T, U, K extends string>(prop: K, val: T, obj: U): U & Record<K, T>;
// assoc(__, val, obj)(prop)
export function assoc<T, U>(__: Placeholder, val: T, obj: U): <K extends PropertyKey>(prop: K) => K extends keyof U ? T extends U[K] ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;

// assoc(prop, __, obj)(val)
export function assoc<U, K extends PropertyKey>(prop: K, __: Placeholder, obj: U): <T>(val: T) => K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;

// assoc(prop, val, obj)
export function assoc<T, U, K extends PropertyKey>(prop: K, val: T, obj: U): K extends keyof U ? U[K] extends T ? U : Record<K, T> & Omit<U, K> : U & Record<K, T>;

0 comments on commit 6027164

Please sign in to comment.