Краткий ответ: вы все делаете правильно.
ReadonlyMap<K, V>
по существу является супертипом из Map<K, V>
, поскольку методы и свойства, которые он имеет, совпадают со свойствами Map<K,V>
. Таким образом, возвращая Map
как ReadonlyMap
, все, что вы делаете, это расширяете тип значения. Кстати, это означает, что вы можете пропустить утверждение типа:
public publicApiMethod(): ReadonlyMap<K, V> {
const map: Map<K, V> = new Map(...);
return map; // no assertion necessary
}
Точно так же, как вы могли бы сделать это:
public anotherMethod(): string | number {
return "hey"; // always "hey", but assignable to string | number
}
Преимущество заключается в том, что вызывающая сторона не может предположить, что возвращаемое значение имеет какой-либо из других Map
методов, а попытка установить или очистить содержимое карты приведет к ошибке времени компиляции, несмотря на то, что эти методы будет действительно существовать во время выполнения. (Или для примера anotherMethod()
вызывающая сторона не может знать, что возвращаемое значение всегда является string
, и не может напрямую вызывать для нее какие-либо строковые методы.)
Этот запрет во время компиляции аналогичен тому, как работает модификатор readonly
. Если для свойства установлено значение readonly
, TypeScript будет жаловаться, если вы попытаетесь изменить его, даже если изменение завершится успешно во время выполнения.
Вы можете, если хотите, реализовать свою собственную версию ReadonlyMap
, которая доступна только для чтения даже во время выполнения, но это того стоит, если у вас есть сценарий использования, который этого требует. Если вы этого не сделаете (и, вероятно, нет), тогда не беспокойтесь об этом и продолжайте делать это так, как вы это делаете.
Надеюсь, это поможет; удачи!