typescriptrecoiljs

Make intersection of two methods in typescript


I have intersection type GetSet and instances of Get and Set. How can I compose the GetSet instance? get & set gives two errors:

type Get = (<T>(a: RecoilValue<T>) => T)
type Set = (<T>(s: RecoilState<T>, u: (((currVal: T) => T) | T)) => void)
export type GetSet = Get & Set;

// some external functions
let get: Get; 
let set: Set;

function callback(getSet: GetSet) {
}

function perform() {
    callback(get & set); // <--- error here
}

Solution

  • calback(get & set) is plain wrong it will change to 0 in JavaScript (try (function () {}) & (function() {}) in chrome console), there is no & operator that will combine functions in JavaScript. type GetSet = Get & Set is a type definition in TypeScript which only means that the definition is a combination of both. However, there is no such thing in JavaScript.

    If you want to pass two functions in JavaScript, you have to either use Tuple/Array or Object Literal.

       callback([get, set]);
       // or
       callback({ get, set });
    

    However, In this case, the callback definition should change as follow,

    type Get = (<T>(a: RecoilValue<T>) => T)
    type Set = (<T>(s: RecoilState<T>, u: (((currVal: T) => T) | T)) => void)
    export type GetSet = { get: Get, set: Set };
    
    // some external functions
    let get: Get; 
    let set: Set;
    
    function callback({ get, set }: GetSet) {
    }
    
    function perform() {
        callback({ get , set }); // <--- this is correct way
    }
    

    You can combine get set as a single function as shown below...

    function getOrSet(... a: any[]) {
        if (a.length === 1) {
            return get(a[0]);        
        }
        return set(a[0], a[1]);
    }
    

    If you look at how jQuery was organized, you can call same method without parameter to get value and if you pass a parameter, it will set the value.

    This might require rewriting many definitions.