В этом руководстве вы узнаете об обобщенных ограничениях в TypeScript.
Рассмотрим следующий пример:
function merge<U, V>(obj1: U, obj2: V) { return { ...obj1, ...obj2 }; }
merge()
— это общая функция, которая объединяет два объекта. Например:
let person = merge( { name: 'John' }, { age: 25 } ); console.log(result);
Выход:
{ name: 'John', age: 25 }
Функция merge()
ожидает два объекта. Однако это не мешает вам передавать не-объект следующим образом:
let person = merge( { name: 'John' }, 25 ); console.log(person);
Выход:
{ name: 'John' }
TypeScript не выдает никаких ошибок.
Вместо работы со всеми типами вы можете добавить ограничение в функцию merge()
, чтобы она работала только с объектами.
Для этого вам нужно перечислить требование в качестве ограничения на то, какими могут быть типы U
и V
.
Чтобы обозначить ограничение, вы используете ключевое слово extends
. Например:
function merge<U extends object, V extends object>(obj1: U, obj2: V) { return { ...obj1, ...obj2 }; }
Поскольку функция merge()
теперь ограничена, она больше не будет работать со всеми типами. Вместо этого он работает только с типом object
.
Следующее приведет к ошибке:
let person = merge( { name: 'John' }, 25 );
Ошибка:
Argument of type '25' is not assignable to parameter of type 'object'.
Использование универсальных ограничений для параметров типа
TypeScript позволяет объявить параметр типа, ограниченный другим параметром типа.
Следующая функция prop()
принимает объект и имя свойства. Он возвращает значение свойства.
function prop<T, K>(obj: T, key: K) { return obj[key]; }
Компилятор выдает следующую ошибку:
Type 'K' cannot be used to index type 'T'.
Чтобы исправить эту ошибку, вы добавляете ограничение к K
, чтобы гарантировать, что это ключ T
следующим образом:
function prop<T, K extends keyof T>(obj: T, key: K) { return obj[key]; }
Если вы передадите в функцию prop
имя свойства, существующее в obj
, компилятор не будет жаловаться. Например:
let str = prop({ name: 'John' }, 'name'); console.log(str);
Выход:
John
Однако, если вы передадите несуществующий ключ в первом аргументе, компилятор выдаст ошибку:
let str = prop({ name: 'John' }, 'age');
Ошибка:
Argument of type '"age"' is not assignable to parameter of type '"name"'.
Заключение
- Используйте ключевое слово
extends
, чтобы ограничить параметр типа определенным типом в TypeScript. - Используйте
extends keyof
для ограничения типа, который является свойством другого объекта.