Repository: Qiskit/qiskit

Issue:
Transpiling fails if the target does not specify properties for measurement instructions
### Environment

- **Qiskit Terra version**: 0.22.0
- **Python version**: 3.9.12
- **Operating system**: Windows 10


### What is happening?

```
Traceback (most recent call last):
  File ".\src\playground.py", line 86, in <module>
    qc_transpiled = transpile(qc, target=target)
  File ".\lib\site-packages\qiskit\compiler\transpiler.py", line 327, in transpile
    unique_transpile_args, shared_args = _parse_transpile_args(
  File ".\lib\site-packages\qiskit\compiler\transpiler.py", line 646, in _parse_transpile_args
    backend_properties = target_to_backend_properties(target)
  File ".\lib\site-packages\qiskit\transpiler\target.py", line 1021, in target_to_backend_properties
    if props.error is not None:
AttributeError: 'NoneType' object has no attribute 'error'
```

### How can we reproduce the issue?

When building a transpiler target, the properties for added instructions are optional. The documentation of `qiskit.transpiler.Target.add_instruction` says `Properties are optional for any instruction implementation, if there are no InstructionProperties available for the backend the value can be None.`. However, it seems this claim is true for all instructions except measurement. 

The below code snippet shows how to construct a very simple target with one qubit and measurement instruction associated with it. The measurement instruction does not have any properties (i.e. it is specified as `None`). Then, this target is used to transpile a circuit, which results into the error pasted above
```
from qiskit import QuantumCircuit
from qiskit.circuit.library import Measure
from qiskit.compiler import transpile
from qiskit.transpiler import Target

target = Target()
target.add_instruction(Measure(), {(0,): None})

qc = QuantumCircuit(1, 1)
qc.measure(0, 0)

transpile(qc, target=target)
```

### What should happen?

The transpilation should not fail

### Any suggestions?

_No response_


Discussion:

Resolving patch:
diff --git a/qiskit/transpiler/target.py b/qiskit/transpiler/target.py
--- a/qiskit/transpiler/target.py
+++ b/qiskit/transpiler/target.py
@@ -1043,24 +1043,25 @@ def target_to_backend_properties(target: Target):
                     continue
                 qubit = qargs[0]
                 props_list = []
-                if props.error is not None:
-                    props_list.append(
-                        {
-                            "date": datetime.datetime.utcnow(),
-                            "name": "readout_error",
-                            "unit": "",
-                            "value": props.error,
-                        }
-                    )
-                if props.duration is not None:
-                    props_list.append(
-                        {
-                            "date": datetime.datetime.utcnow(),
-                            "name": "readout_length",
-                            "unit": "s",
-                            "value": props.duration,
-                        }
-                    )
+                if props is not None:
+                    if props.error is not None:
+                        props_list.append(
+                            {
+                                "date": datetime.datetime.utcnow(),
+                                "name": "readout_error",
+                                "unit": "",
+                                "value": props.error,
+                            }
+                        )
+                    if props.duration is not None:
+                        props_list.append(
+                            {
+                                "date": datetime.datetime.utcnow(),
+                                "name": "readout_length",
+                                "unit": "s",
+                                "value": props.duration,
+                            }
+                        )
                 if not props_list:
                     qubit_props = {}
                     break


Test patch:
diff --git a/test/python/compiler/test_transpiler.py b/test/python/compiler/test_transpiler.py
--- a/test/python/compiler/test_transpiler.py
+++ b/test/python/compiler/test_transpiler.py
@@ -1726,6 +1726,19 @@ def test_qasm3_output_control_flow(self, optimization_level):
         # itself doesn't throw an error, though.
         self.assertIsInstance(qasm3.dumps(transpiled).strip(), str)
 
+    @data(0, 1, 2, 3)
+    def test_transpile_target_no_measurement_error(self, opt_level):
+        """Test that transpile with a target which contains ideal measurement works
+
+        Reproduce from https://github.com/Qiskit/qiskit-terra/issues/8969
+        """
+        target = Target()
+        target.add_instruction(Measure(), {(0,): None})
+        qc = QuantumCircuit(1, 1)
+        qc.measure(0, 0)
+        res = transpile(qc, target=target, optimization_level=opt_level)
+        self.assertEqual(qc, res)
+
 
 class StreamHandlerRaiseException(StreamHandler):
     """Handler class that will raise an exception on formatting errors."""