Some questions about Interface ids

:1234: Code to reproduce

Contract A

pragma solidity >= 0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/ERC165.sol";

contract ContractA is ERC165 {

    constructor() {}

    function supportsInterface(bytes4 interfaceID) public view override returns (bool){
        return interfaceID == 0x12345678;
    }

    function getInterface0() external view returns (bytes4) {
        return type(ERC165).interfaceId;
    }

    //function getInterface1() external view returns (bytes4) {
    //    return type(ERC20).interfaceId;
    //}

    //function getInterface2() external view returns (bytes4) {
    //    return type(ERC721).interfaceId;
    //}

    function getInterface3() external view returns (bytes4) {
        return type(IERC20).interfaceId;
    }
    
}

ContractB:

import "./ContractA.sol";

contract ContractB is ContractA {

    constructor() {}

    function getInterface01() external view returns (bytes4) {
        return type(ContractA).interfaceId;
    }

}

Hello,

I just study a bit about interfaceIds...
And got some question about it. Hopefully someone here can help me out.
In the docs (https://docs.soliditylang.org/en/latest/units-and-global-variables.html#type-information) is written that you can access an interface id with "type(Contract).interfaceId"

But:

  1. It works for me with ERC165 contract but not with ERC20.
  2. But it works for IERC20...
  3. I do not see any implementation in any contract of "interfaceId".
  4. I fail at the try to implement my own id. (In ContractA i can manipulate the return value of "supportsInterface" - but that does not make it possible to compile "type(ContractA).interfaceId" ->

TypeError: Member "interfaceId" not found or not visible after argument-dependent lookup in type(contract ContractA).

So my questions would be:

  1. Why does some contracts have the id (ERC165 return of "getInterface0()") and some not (ERC20 - even when ERC20 is IERC20)?
  2. How does eg. IERC20 get an id?
    2.1. My own interfaces gets also an id - but how? Can I manipulate them?