diff --git a/mypy/subtypes.py b/mypy/subtypes.py
index a63db93fd9cb..b64876ada87c 100644
--- a/mypy/subtypes.py
+++ b/mypy/subtypes.py
@@ -1959,6 +1959,16 @@ def covers_at_runtime(item: Type, supertype: Type) -> bool:
     item = get_proper_type(item)
     supertype = get_proper_type(supertype)
 
+    # Left `Any` or `Type[Any]` type will never be covered at runtime:
+    if isinstance(item, AnyType) or (
+        isinstance(item, TypeType) and isinstance(item.item, AnyType)
+    ):
+        return False
+
+    if isinstance(item, (CallableType, TypeType)) and item.is_singleton_type():
+        if is_proper_subtype(item, supertype):
+            return True
+
     # Since runtime type checks will ignore type arguments, erase the types.
     supertype = erase_type(supertype)
     if is_proper_subtype(
diff --git a/mypy/types.py b/mypy/types.py
index 897e19d6ee19..bb3645e1b132 100644
--- a/mypy/types.py
+++ b/mypy/types.py
@@ -2167,6 +2167,9 @@ def with_unpacked_kwargs(self) -> NormalizedCallableType:
             )
         )
 
+    def is_singleton_type(self) -> bool:
+        return self.is_type_obj() and self.type_object().is_final
+
     def with_normalized_var_args(self) -> Self:
         var_arg = self.var_arg()
         if not var_arg or not isinstance(var_arg.typ, UnpackType):
@@ -3111,6 +3114,11 @@ def __eq__(self, other: object) -> bool:
             return NotImplemented
         return self.item == other.item
 
+    def is_singleton_type(self) -> bool:
+        return (isinstance(self.item, Instance) and self.item.type.is_final) or isinstance(
+            self.item, NoneType
+        )
+
     def serialize(self) -> JsonDict:
         return {".class": "TypeType", "item": self.item.serialize()}
 
diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test
index d740708991d0..827a8981edfa 100644
--- a/test-data/unit/check-narrowing.test
+++ b/test-data/unit/check-narrowing.test
@@ -1374,7 +1374,102 @@ def g() -> None:
     foo()
 [builtins fixtures/dict.pyi]
 
+[case testNarrowingIsFinalType]
+from typing import Type, Union
+from typing_extensions import final
+
+@final
+class Mark: ...
+
+@final
+class Other: ...
+
+x: Union[Type[Mark], Type[Other], Type[None], int]
+
+if x is Mark:
+    reveal_type(x)  # N: Revealed type is "Type[__main__.Mark]"
+else:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Other], Type[None], builtins.int]"
+
+if x is not Mark:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Other], Type[None], builtins.int]"
+else:
+    reveal_type(x)  # N: Revealed type is "Type[__main__.Mark]"
+
+y: Type[Mark] = Mark
+if x is y:
+    reveal_type(x)  # N: Revealed type is "Type[__main__.Mark]"
+else:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Other], Type[None], builtins.int]"
+
+if x is not y:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Other], Type[None], builtins.int]"
+else:
+    reveal_type(x)  # N: Revealed type is "Type[__main__.Mark]"
+
+if x is type(None):
+    reveal_type(x)  # N: Revealed type is "Type[None]"
+else:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Mark], Type[__main__.Other], builtins.int]"
+
+if x is not type(None):
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Mark], Type[__main__.Other], builtins.int]"
+else:
+    reveal_type(x)  # N: Revealed type is "Type[None]"
+
+z: Type[None]
+if x is z:
+    reveal_type(x)  # N: Revealed type is "Type[None]"
+else:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Mark], Type[__main__.Other], builtins.int]"
+
+if x is not z:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Mark], Type[__main__.Other], builtins.int]"
+else:
+    reveal_type(x)  # N: Revealed type is "Type[None]"
+[builtins fixtures/isinstancelist.pyi]
+
+
+[case testNarrowingAnyAgainstFinalType]
+from typing import Type, Any
+from typing_extensions import final
+
+@final
+class Mark: ...
+
+x: Any
+if x is Mark:
+    reveal_type(x)  # N: Revealed type is "def () -> __main__.Mark"
+else:
+    reveal_type(x)  # N: Revealed type is "Any"
+
+y: Type[Any]
+if y is Mark:
+    reveal_type(y)  # N: Revealed type is "Type[__main__.Mark]"
+else:
+    reveal_type(y)  # N: Revealed type is "Type[Any]"
 
+[builtins fixtures/isinstancelist.pyi]
+
+
+[case testNarrowingIsNonFinalType]
+from typing import Type, Union
+
+class Mark: ...
+
+x: Union[Type[Mark], Type[None], int]
+
+if x is Mark:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Mark], Type[None], builtins.int]"
+else:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Mark], Type[None], builtins.int]"
+
+y: Type[Mark] = Mark
+if x is y:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Mark], Type[None], builtins.int]"
+else:
+    reveal_type(x)  # N: Revealed type is "Union[Type[__main__.Mark], Type[None], builtins.int]"
+[builtins fixtures/isinstancelist.pyi]
 [case testNarrowingOptionalEqualsNone]
 from typing import Optional