diff --git a/.strict-typing b/.strict-typing
index b664fc3b886b22bdf8d8bb47f680130a774b7fa5..64fbcb9e82dccce7c735019d6de5a01bee7b61db 100644
--- a/.strict-typing
+++ b/.strict-typing
@@ -87,6 +87,7 @@ homeassistant.components.recorder.statistics
 homeassistant.components.remote.*
 homeassistant.components.renault.*
 homeassistant.components.rituals_perfume_genie.*
+homeassistant.components.samsungtv.*
 homeassistant.components.scene.*
 homeassistant.components.select.*
 homeassistant.components.sensor.*
diff --git a/homeassistant/components/samsungtv/__init__.py b/homeassistant/components/samsungtv/__init__.py
index 773c340d7b9c45c277188c577538cccddc5d9f64..f55dc0639bafbbe3e4e2c6a8488b45315c8df008 100644
--- a/homeassistant/components/samsungtv/__init__.py
+++ b/homeassistant/components/samsungtv/__init__.py
@@ -1,13 +1,16 @@
 """The Samsung TV integration."""
+from __future__ import annotations
+
 from functools import partial
 import socket
+from typing import Any
 
 import getmac
 import voluptuous as vol
 
 from homeassistant import config_entries
 from homeassistant.components.media_player.const import DOMAIN as MP_DOMAIN
-from homeassistant.config_entries import ConfigEntryNotReady
+from homeassistant.config_entries import ConfigEntry, ConfigEntryNotReady
 from homeassistant.const import (
     CONF_HOST,
     CONF_MAC,
@@ -17,10 +20,17 @@ from homeassistant.const import (
     CONF_TOKEN,
     EVENT_HOMEASSISTANT_STOP,
 )
-from homeassistant.core import callback
+from homeassistant.core import Event, HomeAssistant, callback
 import homeassistant.helpers.config_validation as cv
-
-from .bridge import SamsungTVBridge, async_get_device_info, mac_from_device_info
+from homeassistant.helpers.typing import ConfigType
+
+from .bridge import (
+    SamsungTVBridge,
+    SamsungTVLegacyBridge,
+    SamsungTVWSBridge,
+    async_get_device_info,
+    mac_from_device_info,
+)
 from .const import (
     CONF_ON_ACTION,
     DEFAULT_NAME,
@@ -32,7 +42,7 @@ from .const import (
 )
 
 
-def ensure_unique_hosts(value):
+def ensure_unique_hosts(value: dict[Any, Any]) -> dict[Any, Any]:
     """Validate that all configs have a unique host."""
     vol.Schema(vol.Unique("duplicate host entries found"))(
         [entry[CONF_HOST] for entry in value]
@@ -64,7 +74,7 @@ CONFIG_SCHEMA = vol.Schema(
 )
 
 
-async def async_setup(hass, config):
+async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
     """Set up the Samsung TV integration."""
     hass.data[DOMAIN] = {}
     if DOMAIN not in config:
@@ -88,7 +98,9 @@ async def async_setup(hass, config):
 
 
 @callback
-def _async_get_device_bridge(data):
+def _async_get_device_bridge(
+    data: dict[str, Any]
+) -> SamsungTVLegacyBridge | SamsungTVWSBridge:
     """Get device bridge."""
     return SamsungTVBridge.get_bridge(
         data[CONF_METHOD],
@@ -98,13 +110,13 @@ def _async_get_device_bridge(data):
     )
 
 
-async def async_setup_entry(hass, entry):
+async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
     """Set up the Samsung TV platform."""
 
     # Initialize bridge
     bridge = await _async_create_bridge_with_updated_data(hass, entry)
 
-    def stop_bridge(event):
+    def stop_bridge(event: Event) -> None:
         """Stop SamsungTV bridge connection."""
         bridge.stop()
 
@@ -117,7 +129,9 @@ async def async_setup_entry(hass, entry):
     return True
 
 
-async def _async_create_bridge_with_updated_data(hass, entry):
+async def _async_create_bridge_with_updated_data(
+    hass: HomeAssistant, entry: ConfigEntry
+) -> SamsungTVLegacyBridge | SamsungTVWSBridge:
     """Create a bridge object and update any missing data in the config entry."""
     updated_data = {}
     host = entry.data[CONF_HOST]
@@ -163,7 +177,7 @@ async def _async_create_bridge_with_updated_data(hass, entry):
     return bridge
 
 
-async def async_unload_entry(hass, entry):
+async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
     """Unload a config entry."""
     unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
     if unload_ok:
@@ -171,7 +185,7 @@ async def async_unload_entry(hass, entry):
     return unload_ok
 
 
-async def async_migrate_entry(hass, config_entry):
+async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
     """Migrate old entry."""
     version = config_entry.version
 
diff --git a/homeassistant/components/samsungtv/bridge.py b/homeassistant/components/samsungtv/bridge.py
index 0d00a0cb94f3f3be594afd70a4c95b3ce626684f..262bf4ce67f09e7a8d25a2ce22122a4ee15e5f08 100644
--- a/homeassistant/components/samsungtv/bridge.py
+++ b/homeassistant/components/samsungtv/bridge.py
@@ -1,6 +1,9 @@
 """samsungctl and samsungtvws bridge classes."""
+from __future__ import annotations
+
 from abc import ABC, abstractmethod
 import contextlib
+from typing import Any
 
 from samsungctl import Remote
 from samsungctl.exceptions import AccessDenied, ConnectionClosed, UnhandledResponse
@@ -17,6 +20,7 @@ from homeassistant.const import (
     CONF_TIMEOUT,
     CONF_TOKEN,
 )
+from homeassistant.core import CALLBACK_TYPE, HomeAssistant
 from homeassistant.helpers.device_registry import format_mac
 
 from .const import (
@@ -37,7 +41,7 @@ from .const import (
 )
 
 
-def mac_from_device_info(info):
+def mac_from_device_info(info: dict[str, Any]) -> str | None:
     """Extract the mac address from the device info."""
     dev_info = info.get("device", {})
     if dev_info.get("networkType") == "wireless" and dev_info.get("wifiMac"):
@@ -45,12 +49,18 @@ def mac_from_device_info(info):
     return None
 
 
-async def async_get_device_info(hass, bridge, host):
+async def async_get_device_info(
+    hass: HomeAssistant,
+    bridge: SamsungTVWSBridge | SamsungTVLegacyBridge | None,
+    host: str,
+) -> tuple[int | None, str | None, dict[str, Any] | None]:
     """Fetch the port, method, and device info."""
     return await hass.async_add_executor_job(_get_device_info, bridge, host)
 
 
-def _get_device_info(bridge, host):
+def _get_device_info(
+    bridge: SamsungTVWSBridge | SamsungTVLegacyBridge, host: str
+) -> tuple[int | None, str | None, dict[str, Any] | None]:
     """Fetch the port, method, and device info."""
     if bridge and bridge.port:
         return bridge.port, bridge.method, bridge.device_info()
@@ -72,40 +82,42 @@ class SamsungTVBridge(ABC):
     """The Base Bridge abstract class."""
 
     @staticmethod
-    def get_bridge(method, host, port=None, token=None):
+    def get_bridge(
+        method: str, host: str, port: int | None = None, token: str | None = None
+    ) -> SamsungTVLegacyBridge | SamsungTVWSBridge:
         """Get Bridge instance."""
         if method == METHOD_LEGACY or port == LEGACY_PORT:
             return SamsungTVLegacyBridge(method, host, port)
         return SamsungTVWSBridge(method, host, port, token)
 
-    def __init__(self, method, host, port):
+    def __init__(self, method: str, host: str, port: int | None = None) -> None:
         """Initialize Bridge."""
         self.port = port
         self.method = method
         self.host = host
-        self.token = None
-        self._remote = None
-        self._callback = None
+        self.token: str | None = None
+        self._remote: Remote | None = None
+        self._callback: CALLBACK_TYPE | None = None
 
-    def register_reauth_callback(self, func):
+    def register_reauth_callback(self, func: CALLBACK_TYPE) -> None:
         """Register a callback function."""
         self._callback = func
 
     @abstractmethod
-    def try_connect(self):
+    def try_connect(self) -> str | None:
         """Try to connect to the TV."""
 
     @abstractmethod
-    def device_info(self):
+    def device_info(self) -> dict[str, Any] | None:
         """Try to gather infos of this TV."""
 
     @abstractmethod
-    def mac_from_device(self):
+    def mac_from_device(self) -> str | None:
         """Try to fetch the mac address of the TV."""
 
-    def is_on(self):
+    def is_on(self) -> bool:
         """Tells if the TV is on."""
-        if self._remote:
+        if self._remote is not None:
             self.close_remote()
 
         try:
@@ -121,7 +133,7 @@ class SamsungTVBridge(ABC):
             # Different reasons, e.g. hostname not resolveable
             return False
 
-    def send_key(self, key):
+    def send_key(self, key: str) -> None:
         """Send a key to the tv and handles exceptions."""
         try:
             # recreate connection if connection was dead
@@ -146,14 +158,14 @@ class SamsungTVBridge(ABC):
             pass
 
     @abstractmethod
-    def _send_key(self, key):
+    def _send_key(self, key: str) -> None:
         """Send the key."""
 
     @abstractmethod
-    def _get_remote(self, avoid_open: bool = False):
+    def _get_remote(self, avoid_open: bool = False) -> Remote:
         """Get Remote object."""
 
-    def close_remote(self):
+    def close_remote(self) -> None:
         """Close remote object."""
         try:
             if self._remote is not None:
@@ -163,16 +175,16 @@ class SamsungTVBridge(ABC):
         except OSError:
             LOGGER.debug("Could not establish connection")
 
-    def _notify_callback(self):
+    def _notify_callback(self) -> None:
         """Notify access denied callback."""
-        if self._callback:
+        if self._callback is not None:
             self._callback()
 
 
 class SamsungTVLegacyBridge(SamsungTVBridge):
     """The Bridge for Legacy TVs."""
 
-    def __init__(self, method, host, port):
+    def __init__(self, method: str, host: str, port: int | None) -> None:
         """Initialize Bridge."""
         super().__init__(method, host, LEGACY_PORT)
         self.config = {
@@ -185,11 +197,11 @@ class SamsungTVLegacyBridge(SamsungTVBridge):
             CONF_TIMEOUT: 1,
         }
 
-    def mac_from_device(self):
+    def mac_from_device(self) -> None:
         """Try to fetch the mac address of the TV."""
         return None
 
-    def try_connect(self):
+    def try_connect(self) -> str:
         """Try to connect to the Legacy TV."""
         config = {
             CONF_NAME: VALUE_CONF_NAME,
@@ -216,11 +228,11 @@ class SamsungTVLegacyBridge(SamsungTVBridge):
             LOGGER.debug("Failing config: %s, error: %s", config, err)
             return RESULT_CANNOT_CONNECT
 
-    def device_info(self):
+    def device_info(self) -> None:
         """Try to gather infos of this device."""
         return None
 
-    def _get_remote(self, avoid_open: bool = False):
+    def _get_remote(self, avoid_open: bool = False) -> Remote:
         """Create or return a remote control instance."""
         if self._remote is None:
             # We need to create a new instance to reconnect.
@@ -238,12 +250,12 @@ class SamsungTVLegacyBridge(SamsungTVBridge):
                 pass
         return self._remote
 
-    def _send_key(self, key):
+    def _send_key(self, key: str) -> None:
         """Send the key using legacy protocol."""
         if remote := self._get_remote():
             remote.control(key)
 
-    def stop(self):
+    def stop(self) -> None:
         """Stop Bridge."""
         LOGGER.debug("Stopping SamsungTVLegacyBridge")
         self.close_remote()
@@ -252,17 +264,19 @@ class SamsungTVLegacyBridge(SamsungTVBridge):
 class SamsungTVWSBridge(SamsungTVBridge):
     """The Bridge for WebSocket TVs."""
 
-    def __init__(self, method, host, port, token=None):
+    def __init__(
+        self, method: str, host: str, port: int | None = None, token: str | None = None
+    ) -> None:
         """Initialize Bridge."""
         super().__init__(method, host, port)
         self.token = token
 
-    def mac_from_device(self):
+    def mac_from_device(self) -> str | None:
         """Try to fetch the mac address of the TV."""
         info = self.device_info()
         return mac_from_device_info(info) if info else None
 
-    def try_connect(self):
+    def try_connect(self) -> str:
         """Try to connect to the Websocket TV."""
         for self.port in WEBSOCKET_PORTS:
             config = {
@@ -286,7 +300,7 @@ class SamsungTVWSBridge(SamsungTVBridge):
                 ) as remote:
                     remote.open()
                     self.token = remote.token
-                    if self.token:
+                    if self.token is None:
                         config[CONF_TOKEN] = "*****"
                 LOGGER.debug("Working config: %s", config)
                 return RESULT_SUCCESS
@@ -304,22 +318,23 @@ class SamsungTVWSBridge(SamsungTVBridge):
 
         return RESULT_CANNOT_CONNECT
 
-    def device_info(self):
+    def device_info(self) -> dict[str, Any] | None:
         """Try to gather infos of this TV."""
-        remote = self._get_remote(avoid_open=True)
-        if not remote:
-            return None
-        with contextlib.suppress(HttpApiError):
-            return remote.rest_device_info()
+        if remote := self._get_remote(avoid_open=True):
+            with contextlib.suppress(HttpApiError):
+                device_info: dict[str, Any] = remote.rest_device_info()
+                return device_info
+
+        return None
 
-    def _send_key(self, key):
+    def _send_key(self, key: str) -> None:
         """Send the key using websocket protocol."""
         if key == "KEY_POWEROFF":
             key = "KEY_POWER"
         if remote := self._get_remote():
             remote.send_key(key)
 
-    def _get_remote(self, avoid_open: bool = False):
+    def _get_remote(self, avoid_open: bool = False) -> Remote:
         """Create or return a remote control instance."""
         if self._remote is None:
             # We need to create a new instance to reconnect.
@@ -344,7 +359,7 @@ class SamsungTVWSBridge(SamsungTVBridge):
                 self._remote = None
         return self._remote
 
-    def stop(self):
+    def stop(self) -> None:
         """Stop Bridge."""
         LOGGER.debug("Stopping SamsungTVWSBridge")
         self.close_remote()
diff --git a/homeassistant/components/samsungtv/config_flow.py b/homeassistant/components/samsungtv/config_flow.py
index da13d0fe70c6b41b30d359a14ac11c05b22bcd88..bcce5eec5ed17a72703498202172ece29f8b0596 100644
--- a/homeassistant/components/samsungtv/config_flow.py
+++ b/homeassistant/components/samsungtv/config_flow.py
@@ -1,5 +1,9 @@
 """Config flow for Samsung TV."""
+from __future__ import annotations
+
 import socket
+from types import MappingProxyType
+from typing import Any
 from urllib.parse import urlparse
 
 import getmac
@@ -25,7 +29,13 @@ from homeassistant.core import callback
 from homeassistant.helpers.device_registry import format_mac
 from homeassistant.helpers.typing import DiscoveryInfoType
 
-from .bridge import SamsungTVBridge, async_get_device_info, mac_from_device_info
+from .bridge import (
+    SamsungTVBridge,
+    SamsungTVLegacyBridge,
+    SamsungTVWSBridge,
+    async_get_device_info,
+    mac_from_device_info,
+)
 from .const import (
     ATTR_PROPERTIES,
     CONF_MANUFACTURER,
@@ -48,11 +58,11 @@ DATA_SCHEMA = vol.Schema({vol.Required(CONF_HOST): str, vol.Required(CONF_NAME):
 SUPPORTED_METHODS = [METHOD_LEGACY, METHOD_WEBSOCKET]
 
 
-def _strip_uuid(udn):
+def _strip_uuid(udn: str) -> str:
     return udn[5:] if udn.startswith("uuid:") else udn
 
 
-def _entry_is_complete(entry):
+def _entry_is_complete(entry: config_entries.ConfigEntry) -> bool:
     """Return True if the config entry information is complete."""
     return bool(entry.unique_id and entry.data.get(CONF_MAC))
 
@@ -62,22 +72,24 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
 
     VERSION = 2
 
-    def __init__(self):
+    def __init__(self) -> None:
         """Initialize flow."""
-        self._reauth_entry = None
-        self._host = None
-        self._mac = None
-        self._udn = None
-        self._manufacturer = None
-        self._model = None
-        self._name = None
-        self._title = None
-        self._id = None
-        self._bridge = None
-        self._device_info = None
-
-    def _get_entry_from_bridge(self):
+        self._reauth_entry: config_entries.ConfigEntry | None = None
+        self._host: str = ""
+        self._mac: str | None = None
+        self._udn: str | None = None
+        self._manufacturer: str | None = None
+        self._model: str | None = None
+        self._name: str | None = None
+        self._title: str = ""
+        self._id: int | None = None
+        self._bridge: SamsungTVLegacyBridge | SamsungTVWSBridge | None = None
+        self._device_info: dict[str, Any] | None = None
+
+    def _get_entry_from_bridge(self) -> data_entry_flow.FlowResult:
         """Get device entry."""
+        assert self._bridge
+
         data = {
             CONF_HOST: self._host,
             CONF_MAC: self._mac,
@@ -94,14 +106,16 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
             data=data,
         )
 
-    async def _async_set_device_unique_id(self, raise_on_progress=True):
+    async def _async_set_device_unique_id(self, raise_on_progress: bool = True) -> None:
         """Set device unique_id."""
         if not await self._async_get_and_check_device_info():
             raise data_entry_flow.AbortFlow(RESULT_NOT_SUPPORTED)
         await self._async_set_unique_id_from_udn(raise_on_progress)
         self._async_update_and_abort_for_matching_unique_id()
 
-    async def _async_set_unique_id_from_udn(self, raise_on_progress=True):
+    async def _async_set_unique_id_from_udn(
+        self, raise_on_progress: bool = True
+    ) -> None:
         """Set the unique id from the udn."""
         assert self._host is not None
         await self.async_set_unique_id(self._udn, raise_on_progress=raise_on_progress)
@@ -110,14 +124,14 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         ):
             raise data_entry_flow.AbortFlow("already_configured")
 
-    def _async_update_and_abort_for_matching_unique_id(self):
+    def _async_update_and_abort_for_matching_unique_id(self) -> None:
         """Abort and update host and mac if we have it."""
         updates = {CONF_HOST: self._host}
         if self._mac:
             updates[CONF_MAC] = self._mac
         self._abort_if_unique_id_configured(updates=updates)
 
-    def _try_connect(self):
+    def _try_connect(self) -> None:
         """Try to connect and check auth."""
         for method in SUPPORTED_METHODS:
             self._bridge = SamsungTVBridge.get_bridge(method, self._host)
@@ -129,7 +143,7 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         LOGGER.debug("No working config found")
         raise data_entry_flow.AbortFlow(RESULT_CANNOT_CONNECT)
 
-    async def _async_get_and_check_device_info(self):
+    async def _async_get_and_check_device_info(self) -> bool:
         """Try to get the device info."""
         _port, _method, info = await async_get_device_info(
             self.hass, self._bridge, self._host
@@ -160,7 +174,9 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         self._device_info = info
         return True
 
-    async def async_step_import(self, user_input=None):
+    async def async_step_import(
+        self, user_input: dict[str, Any]
+    ) -> data_entry_flow.FlowResult:
         """Handle configuration by yaml file."""
         # We need to import even if we cannot validate
         # since the TV may be off at startup
@@ -177,21 +193,24 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
             data=user_input,
         )
 
-    async def _async_set_name_host_from_input(self, user_input):
+    async def _async_set_name_host_from_input(self, user_input: dict[str, Any]) -> None:
         try:
             self._host = await self.hass.async_add_executor_job(
                 socket.gethostbyname, user_input[CONF_HOST]
             )
         except socket.gaierror as err:
             raise data_entry_flow.AbortFlow(RESULT_UNKNOWN_HOST) from err
-        self._name = user_input.get(CONF_NAME, self._host)
+        self._name = user_input.get(CONF_NAME, self._host) or ""
         self._title = self._name
 
-    async def async_step_user(self, user_input=None):
+    async def async_step_user(
+        self, user_input: dict[str, Any] | None = None
+    ) -> data_entry_flow.FlowResult:
         """Handle a flow initialized by the user."""
         if user_input is not None:
             await self._async_set_name_host_from_input(user_input)
             await self.hass.async_add_executor_job(self._try_connect)
+            assert self._bridge
             self._async_abort_entries_match({CONF_HOST: self._host})
             if self._bridge.method != METHOD_LEGACY:
                 # Legacy bridge does not provide device info
@@ -201,7 +220,7 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         return self.async_show_form(step_id="user", data_schema=DATA_SCHEMA)
 
     @callback
-    def _async_update_existing_host_entry(self):
+    def _async_update_existing_host_entry(self) -> config_entries.ConfigEntry | None:
         """Check existing entries and update them.
 
         Returns the existing entry if it was updated.
@@ -209,7 +228,7 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         for entry in self._async_current_entries(include_ignore=False):
             if entry.data[CONF_HOST] != self._host:
                 continue
-            entry_kw_args = {}
+            entry_kw_args: dict = {}
             if self.unique_id and entry.unique_id is None:
                 entry_kw_args["unique_id"] = self.unique_id
             if self._mac and not entry.data.get(CONF_MAC):
@@ -222,7 +241,7 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
                 return entry
         return None
 
-    async def _async_start_discovery_with_mac_address(self):
+    async def _async_start_discovery_with_mac_address(self) -> None:
         """Start discovery."""
         assert self._host is not None
         if (entry := self._async_update_existing_host_entry()) and entry.unique_id:
@@ -232,25 +251,28 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         self._async_abort_if_host_already_in_progress()
 
     @callback
-    def _async_abort_if_host_already_in_progress(self):
+    def _async_abort_if_host_already_in_progress(self) -> None:
         self.context[CONF_HOST] = self._host
         for progress in self._async_in_progress():
             if progress.get("context", {}).get(CONF_HOST) == self._host:
                 raise data_entry_flow.AbortFlow("already_in_progress")
 
     @callback
-    def _abort_if_manufacturer_is_not_samsung(self):
+    def _abort_if_manufacturer_is_not_samsung(self) -> None:
         if not self._manufacturer or not self._manufacturer.lower().startswith(
             "samsung"
         ):
             raise data_entry_flow.AbortFlow(RESULT_NOT_SUPPORTED)
 
-    async def async_step_ssdp(self, discovery_info: DiscoveryInfoType):
+    async def async_step_ssdp(
+        self, discovery_info: DiscoveryInfoType
+    ) -> data_entry_flow.FlowResult:
         """Handle a flow initialized by ssdp discovery."""
         LOGGER.debug("Samsung device found via SSDP: %s", discovery_info)
-        model_name = discovery_info.get(ATTR_UPNP_MODEL_NAME)
+        model_name: str = discovery_info.get(ATTR_UPNP_MODEL_NAME) or ""
         self._udn = _strip_uuid(discovery_info[ATTR_UPNP_UDN])
-        self._host = urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname
+        if hostname := urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname:
+            self._host = hostname
         await self._async_set_unique_id_from_udn()
         self._manufacturer = discovery_info[ATTR_UPNP_MANUFACTURER]
         self._abort_if_manufacturer_is_not_samsung()
@@ -263,7 +285,9 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         self.context["title_placeholders"] = {"device": self._title}
         return await self.async_step_confirm()
 
-    async def async_step_dhcp(self, discovery_info: DiscoveryInfoType):
+    async def async_step_dhcp(
+        self, discovery_info: DiscoveryInfoType
+    ) -> data_entry_flow.FlowResult:
         """Handle a flow initialized by dhcp discovery."""
         LOGGER.debug("Samsung device found via DHCP: %s", discovery_info)
         self._mac = discovery_info[MAC_ADDRESS]
@@ -273,7 +297,9 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         self.context["title_placeholders"] = {"device": self._title}
         return await self.async_step_confirm()
 
-    async def async_step_zeroconf(self, discovery_info: DiscoveryInfoType):
+    async def async_step_zeroconf(
+        self, discovery_info: DiscoveryInfoType
+    ) -> data_entry_flow.FlowResult:
         """Handle a flow initialized by zeroconf discovery."""
         LOGGER.debug("Samsung device found via ZEROCONF: %s", discovery_info)
         self._mac = format_mac(discovery_info[ATTR_PROPERTIES]["deviceid"])
@@ -283,11 +309,14 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
         self.context["title_placeholders"] = {"device": self._title}
         return await self.async_step_confirm()
 
-    async def async_step_confirm(self, user_input=None):
+    async def async_step_confirm(
+        self, user_input: dict[str, Any] | None = None
+    ) -> data_entry_flow.FlowResult:
         """Handle user-confirmation of discovered node."""
         if user_input is not None:
 
             await self.hass.async_add_executor_job(self._try_connect)
+            assert self._bridge
             return self._get_entry_from_bridge()
 
         self._set_confirm_only()
@@ -295,11 +324,14 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
             step_id="confirm", description_placeholders={"device": self._title}
         )
 
-    async def async_step_reauth(self, data):
+    async def async_step_reauth(
+        self, data: MappingProxyType[str, Any]
+    ) -> data_entry_flow.FlowResult:
         """Handle configuration by re-auth."""
         self._reauth_entry = self.hass.config_entries.async_get_entry(
             self.context["entry_id"]
         )
+        assert self._reauth_entry
         data = self._reauth_entry.data
         if data.get(CONF_MODEL) and data.get(CONF_NAME):
             self._title = f"{data[CONF_NAME]} ({data[CONF_MODEL]})"
@@ -307,9 +339,12 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
             self._title = data.get(CONF_NAME) or data[CONF_HOST]
         return await self.async_step_reauth_confirm()
 
-    async def async_step_reauth_confirm(self, user_input=None):
+    async def async_step_reauth_confirm(
+        self, user_input: dict[str, Any] | None = None
+    ) -> data_entry_flow.FlowResult:
         """Confirm reauth."""
         errors = {}
+        assert self._reauth_entry
         if user_input is not None:
             bridge = SamsungTVBridge.get_bridge(
                 self._reauth_entry.data[CONF_METHOD], self._reauth_entry.data[CONF_HOST]
diff --git a/homeassistant/components/samsungtv/media_player.py b/homeassistant/components/samsungtv/media_player.py
index 7efdcdcd43908dd025ad729bbfaf33dfbf444e3f..4e17c65b461dce7c72c7fbab23e51c4e24e2c999 100644
--- a/homeassistant/components/samsungtv/media_player.py
+++ b/homeassistant/components/samsungtv/media_player.py
@@ -1,6 +1,9 @@
 """Support for interface with an Samsung TV."""
+from __future__ import annotations
+
 import asyncio
-from datetime import timedelta
+from datetime import datetime, timedelta
+from typing import Any
 
 import voluptuous as vol
 from wakeonlan import send_magic_packet
@@ -19,11 +22,18 @@ from homeassistant.components.media_player.const import (
     SUPPORT_VOLUME_MUTE,
     SUPPORT_VOLUME_STEP,
 )
-from homeassistant.config_entries import SOURCE_REAUTH
+from homeassistant.components.samsungtv.bridge import (
+    SamsungTVLegacyBridge,
+    SamsungTVWSBridge,
+)
+from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntry
 from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME, STATE_OFF, STATE_ON
+from homeassistant.core import HomeAssistant
 from homeassistant.helpers import entity_component
 import homeassistant.helpers.config_validation as cv
 from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
+from homeassistant.helpers.entity import DeviceInfo
+from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from homeassistant.helpers.script import Script
 from homeassistant.util import dt as dt_util
 
@@ -59,7 +69,9 @@ SCAN_INTERVAL_PLUS_OFF_TIME = entity_component.DEFAULT_SCAN_INTERVAL + timedelta
 )
 
 
-async def async_setup_entry(hass, entry, async_add_entities):
+async def async_setup_entry(
+    hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
+) -> None:
     """Set up the Samsung TV from a config entry."""
     bridge = hass.data[DOMAIN][entry.entry_id]
 
@@ -77,33 +89,38 @@ async def async_setup_entry(hass, entry, async_add_entities):
 class SamsungTVDevice(MediaPlayerEntity):
     """Representation of a Samsung TV."""
 
-    def __init__(self, bridge, config_entry, on_script):
+    def __init__(
+        self,
+        bridge: SamsungTVLegacyBridge | SamsungTVWSBridge,
+        config_entry: ConfigEntry,
+        on_script: Script | None,
+    ) -> None:
         """Initialize the Samsung device."""
         self._config_entry = config_entry
-        self._host = config_entry.data[CONF_HOST]
-        self._mac = config_entry.data.get(CONF_MAC)
-        self._manufacturer = config_entry.data.get(CONF_MANUFACTURER)
-        self._model = config_entry.data.get(CONF_MODEL)
-        self._name = config_entry.data.get(CONF_NAME)
+        self._host: str | None = config_entry.data[CONF_HOST]
+        self._mac: str | None = config_entry.data.get(CONF_MAC)
+        self._manufacturer: str | None = config_entry.data.get(CONF_MANUFACTURER)
+        self._model: str | None = config_entry.data.get(CONF_MODEL)
+        self._name: str | None = config_entry.data.get(CONF_NAME)
         self._on_script = on_script
         self._uuid = config_entry.unique_id
         # Assume that the TV is not muted
-        self._muted = False
+        self._muted: bool = False
         # Assume that the TV is in Play mode
-        self._playing = True
-        self._state = None
+        self._playing: bool = True
+        self._state: str | None = None
         # Mark the end of a shutdown command (need to wait 15 seconds before
         # sending the next command to avoid turning the TV back ON).
-        self._end_of_power_off = None
+        self._end_of_power_off: datetime | None = None
         self._bridge = bridge
         self._auth_failed = False
         self._bridge.register_reauth_callback(self.access_denied)
 
-    def access_denied(self):
+    def access_denied(self) -> None:
         """Access denied callback."""
         LOGGER.debug("Access denied in getting remote object")
         self._auth_failed = True
-        self.hass.add_job(
+        self.hass.async_create_task(
             self.hass.config_entries.flow.async_init(
                 DOMAIN,
                 context={
@@ -114,7 +131,7 @@ class SamsungTVDevice(MediaPlayerEntity):
             )
         )
 
-    def update(self):
+    def update(self) -> None:
         """Update state of device."""
         if self._auth_failed:
             return
@@ -123,82 +140,83 @@ class SamsungTVDevice(MediaPlayerEntity):
         else:
             self._state = STATE_ON if self._bridge.is_on() else STATE_OFF
 
-    def send_key(self, key):
+    def send_key(self, key: str) -> None:
         """Send a key to the tv and handles exceptions."""
         if self._power_off_in_progress() and key != "KEY_POWEROFF":
             LOGGER.info("TV is powering off, not sending command: %s", key)
             return
         self._bridge.send_key(key)
 
-    def _power_off_in_progress(self):
+    def _power_off_in_progress(self) -> bool:
         return (
             self._end_of_power_off is not None
             and self._end_of_power_off > dt_util.utcnow()
         )
 
     @property
-    def unique_id(self) -> str:
+    def unique_id(self) -> str | None:
         """Return the unique ID of the device."""
         return self._uuid
 
     @property
-    def name(self):
+    def name(self) -> str | None:
         """Return the name of the device."""
         return self._name
 
     @property
-    def state(self):
+    def state(self) -> str | None:
         """Return the state of the device."""
         return self._state
 
     @property
-    def available(self):
+    def available(self) -> bool:
         """Return the availability of the device."""
         if self._auth_failed:
             return False
         return (
             self._state == STATE_ON
-            or self._on_script
-            or self._mac
+            or self._on_script is not None
+            or self._mac is not None
             or self._power_off_in_progress()
         )
 
     @property
-    def device_info(self):
+    def device_info(self) -> DeviceInfo | None:
         """Return device specific attributes."""
-        info = {
+        info: DeviceInfo = {
             "name": self.name,
-            "identifiers": {(DOMAIN, self.unique_id)},
             "manufacturer": self._manufacturer,
             "model": self._model,
         }
+        if self.unique_id:
+            info["identifiers"] = {(DOMAIN, self.unique_id)}
         if self._mac:
             info["connections"] = {(CONNECTION_NETWORK_MAC, self._mac)}
         return info
 
     @property
-    def is_volume_muted(self):
+    def is_volume_muted(self) -> bool:
         """Boolean if volume is currently muted."""
         return self._muted
 
     @property
-    def source_list(self):
+    def source_list(self) -> list:
         """List of available input sources."""
         return list(SOURCES)
 
     @property
-    def supported_features(self):
+    def supported_features(self) -> int:
         """Flag media player features that are supported."""
         if self._on_script or self._mac:
             return SUPPORT_SAMSUNGTV | SUPPORT_TURN_ON
         return SUPPORT_SAMSUNGTV
 
     @property
-    def device_class(self):
+    def device_class(self) -> str:
         """Set the device class to TV."""
         return DEVICE_CLASS_TV
 
-    def turn_off(self):
+    def turn_off(self) -> None:
         """Turn off media player."""
         self._end_of_power_off = dt_util.utcnow() + SCAN_INTERVAL_PLUS_OFF_TIME
 
@@ -206,44 +224,46 @@ class SamsungTVDevice(MediaPlayerEntity):
         # Force closing of remote session to provide instant UI feedback
         self._bridge.close_remote()
 
-    def volume_up(self):
+    def volume_up(self) -> None:
         """Volume up the media player."""
         self.send_key("KEY_VOLUP")
 
-    def volume_down(self):
+    def volume_down(self) -> None:
         """Volume down media player."""
         self.send_key("KEY_VOLDOWN")
 
-    def mute_volume(self, mute):
+    def mute_volume(self, mute: bool) -> None:
         """Send mute command."""
         self.send_key("KEY_MUTE")
 
-    def media_play_pause(self):
+    def media_play_pause(self) -> None:
         """Simulate play pause media player."""
         if self._playing:
             self.media_pause()
         else:
             self.media_play()
 
-    def media_play(self):
+    def media_play(self) -> None:
         """Send play command."""
         self._playing = True
         self.send_key("KEY_PLAY")
 
-    def media_pause(self):
+    def media_pause(self) -> None:
         """Send media pause command to media player."""
         self._playing = False
         self.send_key("KEY_PAUSE")
 
-    def media_next_track(self):
+    def media_next_track(self) -> None:
         """Send next track command."""
         self.send_key("KEY_CHUP")
 
-    def media_previous_track(self):
+    def media_previous_track(self) -> None:
         """Send the previous track command."""
         self.send_key("KEY_CHDOWN")
 
-    async def async_play_media(self, media_type, media_id, **kwargs):
+    async def async_play_media(
+        self, media_type: str, media_id: str, **kwargs: Any
+    ) -> None:
         """Support changing a channel."""
         if media_type != MEDIA_TYPE_CHANNEL:
             LOGGER.error("Unsupported media type")
@@ -261,21 +281,21 @@ class SamsungTVDevice(MediaPlayerEntity):
             await asyncio.sleep(KEY_PRESS_TIMEOUT, self.hass.loop)
         await self.hass.async_add_executor_job(self.send_key, "KEY_ENTER")
 
-    def _wake_on_lan(self):
+    def _wake_on_lan(self) -> None:
         """Wake the device via wake on lan."""
         send_magic_packet(self._mac, ip_address=self._host)
         # If the ip address changed since we last saw the device
         # broadcast a packet as well
         send_magic_packet(self._mac)
 
-    async def async_turn_on(self):
+    async def async_turn_on(self) -> None:
         """Turn the media player on."""
         if self._on_script:
             await self._on_script.async_run(context=self._context)
         elif self._mac:
             await self.hass.async_add_executor_job(self._wake_on_lan)
 
-    def select_source(self, source):
+    def select_source(self, source: str) -> None:
         """Select input source."""
         if source not in SOURCES:
             LOGGER.error("Unsupported source")
diff --git a/homeassistant/components/samsungtv/strings.json b/homeassistant/components/samsungtv/strings.json
index f92990e6163feb911369eba7ab17069b5ef48cc9..89ac85f85ebd2911c4c85ff04b69d1f45938f027 100644
--- a/homeassistant/components/samsungtv/strings.json
+++ b/homeassistant/components/samsungtv/strings.json
@@ -14,7 +14,7 @@
       },
       "reauth_confirm": {
         "description": "After submitting, accept the the popup on {device} requesting authorization within 30 seconds."
-      }      
+      }
     },
     "error": {
       "auth_missing": "[%key:component::samsungtv::config::abort::auth_missing%]"
@@ -27,7 +27,8 @@
       "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
       "not_supported": "This Samsung device is currently not supported.",
       "unknown": "[%key:common::config_flow::error::unknown%]",
-      "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
+      "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
+      "missing_config_entry": "This Samsung device doesn't have a configuration entry."
     }
   }
 }
\ No newline at end of file
diff --git a/homeassistant/components/samsungtv/translations/en.json b/homeassistant/components/samsungtv/translations/en.json
index 91576e76ee51b98fa81a77a8d0fc58f91ef2ce6a..fa5369012c098110a3ce123633a6550230356793 100644
--- a/homeassistant/components/samsungtv/translations/en.json
+++ b/homeassistant/components/samsungtv/translations/en.json
@@ -6,6 +6,7 @@
             "auth_missing": "Home Assistant is not authorized to connect to this Samsung TV. Check your TV's External Device Manager settings to authorize Home Assistant.",
             "cannot_connect": "Failed to connect",
             "id_missing": "This Samsung device doesn't have a SerialNumber.",
+            "missing_config_entry": "This Samsung device doesn't have a configuration entry.",
             "not_supported": "This Samsung device is currently not supported.",
             "reauth_successful": "Re-authentication was successful",
             "unknown": "Unexpected error"
@@ -16,8 +17,7 @@
         "flow_title": "{device}",
         "step": {
             "confirm": {
-                "description": "Do you want to set up {device}? If you never connected Home Assistant before you should see a popup on your TV asking for authorization.",
-                "title": "Samsung TV"
+                "description": "Do you want to set up {device}? If you never connected Home Assistant before you should see a popup on your TV asking for authorization."
             },
             "reauth_confirm": {
                 "description": "After submitting, accept the the popup on {device} requesting authorization within 30 seconds."
diff --git a/mypy.ini b/mypy.ini
index e8524d236b38d1fe47a71b170c9a743422eb0530..084355c2beb25cd23f25beec77497a7ff0583d03 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -968,6 +968,17 @@ no_implicit_optional = true
 warn_return_any = true
 warn_unreachable = true
 
+[mypy-homeassistant.components.samsungtv.*]
+check_untyped_defs = true
+disallow_incomplete_defs = true
+disallow_subclassing_any = true
+disallow_untyped_calls = true
+disallow_untyped_decorators = true
+disallow_untyped_defs = true
+no_implicit_optional = true
+warn_return_any = true
+warn_unreachable = true
+
 [mypy-homeassistant.components.scene.*]
 check_untyped_defs = true
 disallow_incomplete_defs = true