0Pricing
TypeScript Academy · 课时

组件泛型——入门

使用 类型参数、约束和类型推断构建可复用组件;安全地传递带类型的渲染属性和键。

组件泛型——入门 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 3 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 3 节课。

入门

目标:使用 <T> 让一个组件适用于多种数据形状。您将传入带类型的渲染属性,约束键,并让 TypeScript 根据使用方式推断 T。

  • 泛型属性和渲染函数
  • 使用 extends 添加约束
  • 不依赖任意类型进行键提取

泛型列表<T>

泛型 List<T> 会让项目和渲染函数保持一致。使用者可以传入任意 T;当 T 明确时,类型推断会正常工作。

import React from "react"

type ListProps<T> = { items: T[]; render: (item: T, index: number) => React.ReactNode }

export function List<T>({ items, render }: ListProps<T>) {
  return <div style={{ display: "grid", gap: 6 }}>{items.map(render)}</div>
}

export default function App() {
  return (
    <div style={{ display: "grid", gap: 12 }}>
      <List<number> items={[1,2,3]} render={(n) => <span>#{n}</span>} />
      <List<{ id: string; name: string }>
        items={[{ id: "u1", name: "Ada" }, { id: "u2", name: "Lin" }]}
        render={(u) => <strong>{u.name}</strong>}
      />
    </div>
  )
}

使用 extends 添加约束

使用 T extends Keyed 要求提供用于键的 id。如果调用者传入的项目缺少必需字段,就会收到错误。

import React from "react"

type Keyed = { id: string }

type KeyListProps<T extends Keyed> = { items: T[]; render: (item: T) => React.ReactNode }

export function KeyList<T extends Keyed>({ items, render }: KeyListProps<T>) {
  return (
    <ul>
      {items.map((x) => (
        <li key={x.id}>{render(x)}</li>
      ))}
    </ul>
  )
}

export default function App() {
  const users = [{ id: "u1", name: "Ada" }, { id: "u2", name: "Lin" }]
  return <KeyList items={users} render={(u) => <span>{u.name}</span>} />
}

推断 T

类型参数通常会根据属性推断出来:这里的 T 来自 items。只有在推断不明确时才添加类型注解。

import React from "react"

type GridProps<T> = { items: T[]; columns?: number; render: (item: T) => React.ReactNode }

export function Grid<T>({ items, columns = 2, render }: GridProps<T>) {
  const css = { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap: 8 }
  return <div style={css as React.CSSProperties}>{items.map(render)}</div>
}

export default function App() {
  const products = [
    { sku: "p1", title: "Mouse", price: 25 },
    { sku: "p2", title: "Keyboard", price: 80 }
  ]
  // T is inferred from products; no need to annotate
  return <Grid items={products} render={(p) => <span>{p.title} — ${p.price}</span>} />
}

渲染辅助工具

提取可复用的 Render<T> 类型,以提高可读性。必要时添加约束(T extends { id: string }),以支持键。

import React from "react"

type Render<T> = (item: T) => React.ReactNode

type TableProps<T extends { id: string }> = { items: T[]; renderRow: Render<T> }

export function Table<T extends { id: string }>({ items, renderRow }: TableProps<T>) {
  return (
    <table>
      <tbody>
        {items.map((x) => (
          <tr key={x.id}><td>{renderRow(x)}</td></tr>
        ))}
      </tbody>
    </table>
  )
}

export default function App() {
  const rows = [ { id: "1", label: "One" }, { id: "2", label: "Two" } ]
  return <Table items={rows} renderRow={(r) => <span>{r.label}</span>} />
}

提示与易错点

提示:

  • 优先使用类型推断,只在有助于提高可读性时添加类型注解。
  • 使用 extends 添加约束,以表达要求。
  • 不要在泛型渲染属性中使用 any;这会破坏类型安全。

泛型组件检查

快速检查:哪种声明正确地定义了泛型 React 组件?

回顾

回顾:使用 <T> 构建可复用组件,使用 extends 为键添加约束,并让类型推断使代码保持简洁。

常见问题解答

「组件泛型——入门」课时是免费的吗?

是的 — 「组件泛型——入门」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 3 节课。

「组件泛型——入门」这节课中我会学到什么?

使用 类型参数、约束和类型推断构建可复用组件;安全地传递带类型的渲染属性和键。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 TypeScript Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 3 节。

「组件泛型——入门」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 TypeScript Academy 课中编写并运行代码吗?

能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 属性与子元素;事件处理器;引用
  2. 状态与 reducer;Context 类型
  3. 组件泛型——入门
← 返回 TypeScript Academy