Here's how I solved it, Ethers v5 & Typescript with OpenZeppelin upgradeable contracts (will work with any type of contract).
import { Contract, ContractInterface, ethers } from "ethers";
import { IERC1155Upgradeable__factory } from "../typechain-types/factories/IERC1155Upgradeable__factory";
import { IERC165Upgradeable__factory } from "../typechain-types/factories/IERC165Upgradeable__factory";
const IERC165UpgradeableInterface = IERC165Upgradeable__factory.createInterface();
const IERC1155UpgradeableInterface = IERC1155Upgradeable__factory.createInterface();
const IERC165InterfaceID = getInterfaceID(IERC165UpgradeableInterface)
// interface ID does not include base contract(s) functions.
const IERC11InterfaceID = getInterfaceID(IERC1155UpgradeableInterface).xor(IERC165InterfaceID);
assert(await contract.supportsInterface(IERC11InterfaceID._hex), "Doesn't support IERC1155Upgradeable");
export function getInterfaceID(contractInterface: ethers.utils.Interface) {
let interfaceID: ethers.BigNumber = ethers.constants.Zero;
const functions: string[] = Object.keys(contractInterface.functions);
for (let i=0; i< functions.length; i++) {
interfaceID = interfaceID.xor(contractInterface.getSighash(functions[i]));
}
return interfaceID;
}
The tricky part is that you have to xor out any base contracts as I looked though the solc compiler and they do not include base contract functions.