# Narrowing using `hasattr()` The builtin function `hasattr()` can be used to narrow nominal and structural types. This is accomplished using an intersection with a synthesized protocol: ```py from typing import final class Foo: ... @final class Bar: ... def f(x: Foo): if hasattr(x, "spam"): reveal_type(x) # revealed: Foo & reveal_type(x.spam) # revealed: object else: reveal_type(x) # revealed: Foo & ~ # TODO: should error and reveal `Unknown` reveal_type(x.spam) # revealed: @Todo(map_with_boundness: intersections with negative contributions) if hasattr(x, "not-an-identifier"): reveal_type(x) # revealed: Foo else: reveal_type(x) # revealed: Foo def g(x: Bar): if hasattr(x, "spam"): reveal_type(x) # revealed: Never reveal_type(x.spam) # revealed: Never else: reveal_type(x) # revealed: Bar # error: [unresolved-attribute] reveal_type(x.spam) # revealed: Unknown def returns_bool() -> bool: return False class Baz: if returns_bool(): x: int = 42 def h(obj: Baz): reveal_type(obj) # revealed: Baz # error: [possibly-unbound-attribute] reveal_type(obj.x) # revealed: int if hasattr(obj, "x"): reveal_type(obj) # revealed: Baz & reveal_type(obj.x) # revealed: int else: reveal_type(obj) # revealed: Baz & ~ # TODO: should emit `[unresolved-attribute]` and reveal `Unknown` reveal_type(obj.x) # revealed: @Todo(map_with_boundness: intersections with negative contributions) ```