Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Опциональные Generic типы в TypeScript
Generic типы позволяют создавать переиспользуемые компоненты и функции, которые работают с различными типами данных. Иногда нужно, чтобы Generic был опциональным с дефолтным значением.
Способ 1: Generic с дефолтным значением
TypeScript позволяет задать дефолтный тип для Generic:
function processData<T = unknown>(data: T): T {
return data
}
const result1 = processData(123)
const result2 = processData<string>('hello')
Способ 2: Multiple Generics с дефолтными значениями
Можно задать дефолтные значения для нескольких Generic типов:
interface Repository<K = unknown, V = unknown> {
get(key: K): V | undefined
set(key: K, value: V): void
}
class UserRepository implements Repository {
private data = new Map()
get(key: unknown): unknown {
return this.data.get(key)
}
set(key: unknown, value: unknown): void {
this.data.set(key, value)
}
}
class TypedRepository implements Repository<string, number> {
private data = new Map<string, number>()
get(key: string): number | undefined {
return this.data.get(key)
}
set(key: string, value: number): void {
this.data.set(key, value)
}
}
Способ 3: Generic для компонентов React
React компоненты часто используют Generic для типизации props:
import { ReactNode } from 'react'
interface CardProps<T = string> {
title: T
content: ReactNode
}
export function Card<T = string>({ title, content }: CardProps<T>) {
return (
<div className="card">
<h2>{title}</h2>
<p>{content}</p>
</div>
)
}
<Card title="Hello" content="World" />
interface ProductTitle {
name: string
price: number
}
<Card<ProductTitle>
title={{ name: 'Laptop', price: 999 }}
content="High-performance device"
/>
Способ 4: Conditional Generics
Можно задать Generic в зависимости от другого Generic:
type ArrayElement<T> = T extends (infer U)[] ? U : T
type StringElement = ArrayElement<string[]>
type NumberElement = ArrayElement<number>
function getFirst<T extends any[]>(arr: T): ArrayElement<T> {
return arr[0]
}
const first1 = getFirst([1, 2, 3])
const first2 = getFirst(['a', 'b'])
Способ 5: Generic с ограничениями (Constraints)
Можно ограничить Generic только определённые типы:
interface HasId {
id: string
}
function getId<T extends HasId = { id: string }>(obj: T): string {
return obj.id
}
getId({ id: '123', name: 'John' })
getId(123) // ERROR
Способ 6: Generic для функций с Optional параметрами
function request<T = null>(url: string, data?: T): Promise<T> {
return fetch(url, {
method: 'POST',
body: data ? JSON.stringify(data) : undefined
})
.then(res => res.json() as Promise<T>)
}
request('/api/users')
interface User {
id: string
name: string
}
request<User>('/api/user', { id: '1', name: 'John' })
Способ 7: Опциональные Generic в Utility Types
type Nullable<T = unknown> = T | null
const value1: Nullable = null
const value2: Nullable<string> = null
const value3: Nullable<string> = 'hello'
type Response<T = any> = {
data: T
status: number
message: string
}
const res1: Response = { data: null, status: 200, message: 'OK' }
const res2: Response<{ id: string }> = { data: { id: '1' }, status: 200, message: 'OK' }
Способ 8: Правильное использование дефолтных Generics
function process<T, U = T>(item: T, processor: (item: T) => U): U {
return processor(item)
}
const result = process(123, (num) => num * 2)
Ключевые моменты
- Дефолтные значения — используй
Generic = Typeдля дефолта - Multiple Generics — каждый может иметь свой дефолт
- Conditional типы — используй
extendsдля зависимостей между Generics - Constraints — ограничивай Generic только нужными типами
- Порядок — Generic с дефолтом должен идти после Generic без дефолта
- React компоненты — часто используют Generic с дефолтами
Опциональные Generics делают TypeScript код более гибким и переиспользуемым.