Не совсем понял момент насчет setTimeout.
В коде мат-диалога есть такое
// The logic that disposes of the overlay depends on the exit animation completing, however
// it isn't guaranteed if the parent view is destroyed while it's running. Add a fallback
// timeout which will clean everything up if the animation hasn't fired within the specified
// amount of time plus 100ms. We don't need to run this outside the NgZone, because for the
// vast majority of cases the timeout will have been cleared before it has the chance to fire.
this._closeFallbackTimeout = setTimeout(() => {
this._overlayRef.dispose();
}, event.totalTime + 100);
overlayRef.dispose()
производит отвязывание от событий клавиатуры.
Как я понял вы по той же причине хотите таймаут, т.к. видимо OnDestroy срабатывает раньше отписок, хотя по коду должен бы после.
Материал довольно сложно устроен и я не стал бы на это полагаться :)
Не проще ли сделать глобальный серсвис с событями клавиатуры, диалоговые окна запускать с disableClose: true, при открытие окна блокировать события сервиса для всех, кроме диалога, а сам диалог закрывать руками при получении события эскейпа и сразу снимать блокирование?