Типы TypeScript Generic невероятно мощны, они позволяют нам создавать композиции шрифтов, что является удивительным шаблоном, который можно использовать в любом проекте TS.

Как использовать универсальные шаблоны?
Использовать универсальные шаблоны очень просто, нам просто нужно сообщить TS, что наш тип принимает другие типы как «полные».
поэтому, если у нас есть какой-то тип A с некоторым динамическим свойством «dynamicObj» в зависимости от места использования трудно определить все типы свойств статически, потому что нам нужно указать все возможные типы для « dynamicObj ».
type B = {
keyA: string;
keyB: string;
}
type C = {
keyT: number;
keyV: boolean;
}
Теперь есть простое и совершенно небезопасное решение: «Просто скажите, что dynamicObject имеет тип any»
Конечно, вы никогда не должны использовать это, имея какой-либо тип в вашем код - это огромный признак «запаха кода».
Кроме того, мы можем пойти дальше неизвестного и выполнить приведение типов после.
type A = {
prop: string;
dynamicObject: unknown;
};
const aWithB: A = {
prop: 'ok',
dynamicObject: {
keyA: 'test',
keyB: 'ok'
}
}
console.log((aWithB.dynamicObject as B).keyA) // NOT SO GOOD 😓
Мы можем пойти еще дальше, используя UnionType для свойства dynamicObject.
type A = {
prop: string;
dynamicObject: B | C;
};
const aWithB: A = {
prop: 'ok',
dynamicObject: {
keyA: 'test',
keyB: 'ok'
}
}
console.log(
(aWithB.dynamicObject as B).keyA // We still need to cast type 😞
)
Итак, давайте посмотрим, как мы можем решить эту проблему с помощью Generic
Если мы укажем тип A как тип, который имеет некоторые свойства, такие как prop и dynamicObj, мы знаем, что dynamicObj зависит от места использования. Затем мы можем определить тип A как тип, который принимает другой тип, который будет типом свойства dynamicObject. Звучит сложнее, чем есть на самом деле.
type A<DynamicObjectType> = {
prop: string;
dynamicObject: DynamicObjectType;
};
const aWithB: A<B> = {
prop: 'ok',
dynamicObject: {
keyA: 'test',
keyB: 'ok'
}
}
const aWithC: A<C> = {
prop: 'ok',
dynamicObject: {
keyT: 11,
keyV: true
}
}
console.log(aWithB.dynamicObject.keyA);
console.log(aWithC.dynamicObject.keyV);
// No warnings, no compilation error 🤩
И это значит, что теперь наш тип A масштабируем для расширения до произвольного числа типов, которые могут быть свойством dynamicObject.
Даже это допустимый тип:
const foo: A<number> = {
prop: "lol",
dynamicObject: 11
}
Вот как можно использовать всю мощь универсальных шаблонов в шрифтовых композициях, довольно просто!
Удачи!