Stai confondendo i livelli di astrazione. Come già sottolineato da altre risposte, CREATE TYPE registra solo un tipo (composito/riga) nel sistema. Mentre una ROW costruttore restituisce effettivamente una riga.
Un tipo di riga creato con ROW costruttore non conserva i nomi delle colonne, il che diventa evidente quando si tenta di convertire la riga in JSON.
Mentre ci sei, ROW è solo una parola rumorosa La maggior parte delle volte. La documentazione:
Demo:
SELECT t AS r1, row_to_json(t) AS j1
, ROW(1, 'x', NUMERIC '42.1') AS r2, row_to_json(ROW(1, 'x', NUMERIC '42.1')) AS j2
, (1, 'x', NUMERIC '42.1') AS r3, row_to_json( (1, 'x', NUMERIC '42.1')) AS j3
, (1, 'x', '42.1')::myrowtype AS r4, row_to_json((1, 'x', '42.1')::myrowtype) AS j4
FROM (SELECT 1, 'x', NUMERIC '42.1') t;
r1 e j1 conserva i nomi delle colonne originali.r2 e j2 non farlo.r3 e j3 sono gli stessi; per dimostrare come ROW è solo rumore.r4 e j4 portano i nomi delle colonne del tipo registrato.
Puoi trasmettere la riga (record) a un tipo di riga registrato se numero e tipi di dati degli elementi corrispondono al tipo di riga - nomi dei campi di input vengono ignorati.