You need to make T a TypeVar:
from typing import Callable, TypeVar
T = TypeVar("T")
U = TypeVar("U")
def foo(arr: list[T], func: Callable[[T], U]) -> None:
func(arr[0])
Within a given call to foo, the arr and func arguments must have the same T:
foo(["asdf", "foo"], lambda x: x.replace("a", "b")) # ok
foo([1, 2, 3], lambda x: x + 1) # ok
foo([1, 2, 3], lambda x: x.replace("foo", "bar")) # error
I suggest using another TypeVar as a placeholder for the return value because Any can easily lead to uncaught errors in the future, whereas a TypeVar with no bound will error if you make bad assumptions about what it supports:
def foo(arr: list[T], func: Callable[[T], Any]) -> None:
x = func(arr[0]) + 2 # ok (danger!)
def foo(arr: list[T], func: Callable[[T], U]) -> None:
x = func(arr[0]) + 2 # error (good!)
If you intend for func to always be a function that returns None, just specify None instead of either U or Any.