Why saving an instantiated object as it's component won't work?

Most values I need from the instantiated object is within it’s component called “TerrainClass”, thus I thought I’d rather send the component to a function instead of the GameObject.

void Start() {
    Generate (Instantiate (instantiatables[UnityEngine.Random.Range(0, instantiatables.Count)].gameObject, Vector3(0.0F, 0.0F, 0.0F), Quaternion.identity) as TerrainClass);
}
void Generate (TerrainClass middle) {
    Debug.Log(middle.Specialty);
}

This script gives me this error message:
NullReferenceException: Object reference not set to an instance of an object
Pools.Generate (.TerrainClass middle) (at Assets/Scripts/Pools.cs:24)
Pools.Start () (at Assets/Scripts/Pools.cs:18)

However, sending the GameObject and then accessing the TerrainClass component works:

void Start () {
    		Generate(Instantiate(instantiatables[UnityEngine.Random.Range(0, instantiatables.Count)].gameObject, new Vector3(0.0F, 0.0F, 0.0F), Quaternion.identity) as GameObject);
    	}
    
    	void Generate (GameObject middle) {
    		Debug.Log (middle.GetComponent<TerrainClass> ().specialty);
}

You’re trying to cast a GameObject to the component TerrainClass which is not a GameObject. The as operator in C# will return null if the cast is invalid which is why you’re getting that error.

You need to instantiate the gameobject, then call GetComponent on the resultant gameobject.

Maybe this is what you’re trying to do? (Spaced it out so its easier to read)

void Start()
{
    Generate(
        Instantiate(
            instantiatables[UnityEngine.Random.Range(0, instantiatables.Count)].gameObject,
            Vector3.zero,
            Quaternion.identity
        ).GetComponent<TerrainClass>()
    );
}
void Generate(TerrainClass middle)
{
    Debug.Log(middle.Specialty);
}