import { NameNode } from 'graphql';
export declare function keyMap<T>(list: readonly T[], keyFn: (item: T) => string): Record<string, T>;
export declare function isEqual<T>(a: T, b: T): boolean;
export declare function isNotEqual<T>(a: T, b: T): boolean;
export declare function isVoid<T>(a: T): a is T & (null | undefined);
export declare function diffArrays<T>(a: T[] | readonly T[], b: T[] | readonly T[]): T[];
export declare function compareLists<T extends {
    name: string | NameNode;
}>(oldList: readonly T[], newList: readonly T[], callbacks?: {
    onAdded?(t: T): void;
    onRemoved?(t: T): void;
    onMutual?(t: {
        newVersion: T;
        oldVersion: T | null;
    }): void;
}): {
    added: T[];
    removed: T[];
    mutual: {
        newVersion: T;
        oldVersion: T;
    }[];
};
/**
 * This is special because directives can be repeated and a name alone is not enough
 * to identify whether or not an instance was changed, added, or removed.
 * The best option is to assume the order is the same, and treat the changes as they come.
 * So `type T @foo` to `type T @foo(f: 'bar') @foo` would be adding an argument `f: 'bar'` and
 * then adding a new directive `@foo`. Rather than adding `@foo(f: 'bar')`
 */
export declare function compareDirectiveLists<T extends {
    name: string | NameNode;
}>(oldList: readonly T[], newList: readonly T[], callbacks?: {
    onAdded?(t: T): void;
    onRemoved?(t: T): void;
    onMutual?(t: {
        newVersion: T;
        oldVersion: T | null;
    }): void;
}): {
    added: T[];
    removed: T[];
    mutual: {
        newVersion: T;
        oldVersion: T;
    }[];
};
export declare function keyMapList<T>(list: readonly T[], keyFn: (item: T) => string): Record<string, [T] & T[]>;
