diff --git a/homeassistant/components/sht31/sensor.py b/homeassistant/components/sht31/sensor.py
index e5f77700409..1415c4856b6 100644
--- a/homeassistant/components/sht31/sensor.py
+++ b/homeassistant/components/sht31/sensor.py
@@ -1,16 +1,24 @@
 """Support for Sensirion SHT31 temperature and humidity sensor."""
+from __future__ import annotations
 
+from dataclasses import dataclass
 from datetime import timedelta
 import logging
 import math
+from typing import Callable
 
 from Adafruit_SHT31 import SHT31
 import voluptuous as vol
 
-from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
+from homeassistant.components.sensor import (
+    PLATFORM_SCHEMA,
+    SensorEntity,
+    SensorEntityDescription,
+)
 from homeassistant.const import (
     CONF_MONITORED_CONDITIONS,
     CONF_NAME,
+    DEVICE_CLASS_HUMIDITY,
     DEVICE_CLASS_TEMPERATURE,
     PERCENTAGE,
     TEMP_CELSIUS,
@@ -25,9 +33,40 @@ CONF_I2C_ADDRESS = "i2c_address"
 DEFAULT_NAME = "SHT31"
 DEFAULT_I2C_ADDRESS = 0x44
 
-SENSOR_TEMPERATURE = "temperature"
-SENSOR_HUMIDITY = "humidity"
-SENSOR_TYPES = (SENSOR_TEMPERATURE, SENSOR_HUMIDITY)
+
+@dataclass
+class SHT31RequiredKeysMixin:
+    """Mixin for required keys."""
+
+    value_fn: Callable[[SHTClient], float | None]
+
+
+@dataclass
+class SHT31SensorEntityDescription(SensorEntityDescription, SHT31RequiredKeysMixin):
+    """Describes SHT31 sensor entity."""
+
+
+SENSOR_TYPES = (
+    SHT31SensorEntityDescription(
+        key="temperature",
+        name="Temperature",
+        device_class=DEVICE_CLASS_TEMPERATURE,
+        native_unit_of_measurement=TEMP_CELSIUS,
+        value_fn=lambda sensor: sensor.temperature,
+    ),
+    SHT31SensorEntityDescription(
+        key="humidity",
+        name="Humidity",
+        device_class=DEVICE_CLASS_HUMIDITY,
+        native_unit_of_measurement=PERCENTAGE,
+        value_fn=lambda sensor: (
+            round(val)  # pylint: disable=undefined-variable
+            if (val := sensor.humidity)
+            else None
+        ),
+    ),
+)
+SENSOR_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
 
 MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10)
 
@@ -36,8 +75,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
         vol.Optional(CONF_I2C_ADDRESS, default=DEFAULT_I2C_ADDRESS): vol.All(
             vol.Coerce(int), vol.Range(min=0x44, max=0x45)
         ),
-        vol.Optional(CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)): vol.All(
-            cv.ensure_list, [vol.In(SENSOR_TYPES)]
+        vol.Optional(CONF_MONITORED_CONDITIONS, default=SENSOR_KEYS): vol.All(
+            cv.ensure_list, [vol.In(SENSOR_KEYS)]
         ),
         vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
     }
@@ -46,8 +85,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
 
 def setup_platform(hass, config, add_entities, discovery_info=None):
     """Set up the sensor platform."""
-
-    i2c_address = config.get(CONF_I2C_ADDRESS)
+    name = config[CONF_NAME]
+    monitored_conditions = config[CONF_MONITORED_CONDITIONS]
+    i2c_address = config[CONF_I2C_ADDRESS]
     sensor = SHT31(address=i2c_address)
 
     try:
@@ -58,17 +98,13 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
         return
     sensor_client = SHTClient(sensor)
 
-    sensor_classes = {
-        SENSOR_TEMPERATURE: SHTSensorTemperature,
-        SENSOR_HUMIDITY: SHTSensorHumidity,
-    }
+    entities = [
+        SHTSensor(sensor_client, name, description)
+        for description in SENSOR_TYPES
+        if description.key in monitored_conditions
+    ]
 
-    devs = []
-    for sensor_type, sensor_class in sensor_classes.items():
-        name = f"{config.get(CONF_NAME)} {sensor_type.capitalize()}"
-        devs.append(sensor_class(sensor_client, name))
-
-    add_entities(devs)
+    add_entities(entities)
 
 
 class SHTClient:
@@ -77,8 +113,8 @@ class SHTClient:
     def __init__(self, adafruit_sht):
         """Initialize the sensor."""
         self.adafruit_sht = adafruit_sht
-        self.temperature = None
-        self.humidity = None
+        self.temperature: float | None = None
+        self.humidity: float | None = None
 
     @Throttle(MIN_TIME_BETWEEN_UPDATES)
     def update(self):
@@ -94,50 +130,16 @@ class SHTClient:
 class SHTSensor(SensorEntity):
     """An abstract SHTSensor, can be either temperature or humidity."""
 
-    def __init__(self, sensor, name):
+    entity_description: SHT31SensorEntityDescription
+
+    def __init__(self, sensor, name, description: SHT31SensorEntityDescription):
         """Initialize the sensor."""
+        self.entity_description = description
         self._sensor = sensor
-        self._name = name
-        self._state = None
 
-    @property
-    def name(self):
-        """Return the name of the sensor."""
-        return self._name
-
-    @property
-    def native_value(self):
-        """Return the state of the sensor."""
-        return self._state
+        self._attr_name = f"{name} {description.name}"
 
     def update(self):
         """Fetch temperature and humidity from the sensor."""
         self._sensor.update()
-
-
-class SHTSensorTemperature(SHTSensor):
-    """Representation of a temperature sensor."""
-
-    _attr_device_class = DEVICE_CLASS_TEMPERATURE
-    _attr_native_unit_of_measurement = TEMP_CELSIUS
-
-    def update(self):
-        """Fetch temperature from the sensor."""
-        super().update()
-        self._state = self._sensor.temperature
-
-
-class SHTSensorHumidity(SHTSensor):
-    """Representation of a humidity sensor."""
-
-    @property
-    def native_unit_of_measurement(self):
-        """Return the unit of measurement."""
-        return PERCENTAGE
-
-    def update(self):
-        """Fetch humidity from the sensor."""
-        super().update()
-        humidity = self._sensor.humidity
-        if humidity is not None:
-            self._state = round(humidity)
+        self._attr_native_value = self.entity_description.value_fn(self._sensor)