Token导航 LogoToken导航

Agent Skill · 前端设计

typescript(TypeScript 开发)

typescript 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

typescript 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 6,472。

总安装 499周安装 21GitHub Stars 公开资料未说明下载 175核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:typescript(TypeScript 开发)
来源仓库:https://github.com/caidanw/skills
仓库路径:skills/typescript
安装命令:
npx skills add https://github.com/caidanw/skills --skill TypeScript
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/caidanw/skills --skill TypeScript

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

typescript 倡导实用主义 TypeScript 风格,平衡类型安全与代码简洁性。适用于中大型前端或 Node.js 项目,利用联合类型、判别属性提升健壮性。推荐小函数、高阶组件与模块化设计,避免过度泛型与复杂类型体操。使用前请配置严格模式与 ESLint 规则,强制暴露潜在类型问题。

类型定义应随代码演进同步更新,禁止“注释式类型”长期漂移。

来源仓库内路径:skills/typescript

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/caidanw/skills --skill TypeScript;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

typescript 怎么安装?

在终端执行 npx skills add https://github.com/caidanw/skills --skill TypeScript。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

typescript 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

typescript 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

typescript 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

typescript 用的人多吗?

公开数据是累计安装 499 次,近一周安装 21 次,下载 175 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

typescript 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
typescript

TypeScript 开发 · 本页

499—需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Pragmatic TypeScript

Write TypeScript that is simple, clear, composable, and soundly typed. Use the good parts of functional style — small functions, higher-order functions, discriminated unions, composition — without dogma. Mutate when it's simpler. Be explicit, not clever. Prioritize readability over density.

1. Simple and Clear

Choose clarity over brevity. Explicit code that's easy to scan beats compact code that requires careful parsing.

// Good — clear, easy to follow
const activeUsers = users.filter(u => u.status === "active")
const emails = activeUsers.map(u => u.email)

// Fine too — chained when each step is obvious
const emails = users
  .filter(u => u.status === "active")
  .map(u => u.email)

// Bad — too dense, hard to debug
const emails = users.reduce((acc, u) => u.status === "active" ? [...acc, u.email] : acc, [] as string[])

Avoid nested ternaries. Use switch, if/else, or early returns for multiple conditions.

// Good
switch (status) {
  case "idle": return null
  case "loading": return <Spinner />
  case "error": return <ErrorBanner error={req.error} />
  case "success": return <Data value={req.data} />
}

// Bad
return status === "idle" ? null : status === "loading" ? <Spinner /> : status === "error" ? <ErrorBanner /> : <Data />

2. Small Functions That Compose

Functions should do one thing and be easy to combine. Name them so the call site reads naturally.

const isActive = (u: User) => u.status === "active"
const byCreatedDesc = (a: User, b: User) => b.createdAt - a.createdAt

const recentActive = users
  .filter(isActive)
  .sort(byCreatedDesc)
  .slice(0, 10)

Extract predicates, comparators, and mappers when they're reused or when inlining them hurts readability. Don't extract trivial one-offs — u => u.id is fine inline.

Keep utility functions in the module that uses them. Only pull them out to a shared file when a second consumer actually appears.

3. Higher-Order Functions

Functions that take or return functions. Use them naturally — they're just functions.

// A function that returns a function
function createValidator<T>(rules: ValidationRule<T>[]) {
  return function validate(value: T): string[] {
    return rules
      .map(rule => rule.check(value) ? null : rule.message)
      .filter((msg): msg is string => msg !== null)
  }
}

// A function that wraps another function
function withRetry<T>(fn: () => Promise<T>, attempts = 3): Promise<T> {
  return fn().catch(err =>
    attempts > 1 ? withRetry(fn, attempts - 1) : Promise.reject(err)
  )
}

Keep the types readable. If a generic signature is getting gnarly, break it up — name intermediate types, use interfaces, add a comment. Don't make people squint.

4. Mutate When It's Simpler

Don't create new objects for the sake of "immutability." TypeScript creates a lot of garbage when you spread compulsively. Mutate local state freely. Use readonly at API boundaries and shared state, not on every field of every type.

// Good — mutating a local array is fine
function buildIndex(items: Item[]): Map<string, Item> {
  const index = new Map<string, Item>()
  for (const item of items) {
    index.set(item.id, item)
  }
  return index
}

// Good — spreading is fine when it's simple
const updated = { ...user, name: newName }

// Bad — spreading inside a loop creating tons of intermediate objects
const result = items.reduce((acc, item) => ({ ...acc, [item.id]: item }), {})

The real test: does the mutation escape the current scope? Mutating a local variable inside a function is always fine. Mutating shared state or arguments passed in is almost always a bug waiting to happen.

Use readonly where it prevents real bugs — public API return types, shared config, state that shouldn't be touched.

interface AppConfig {
  readonly apiUrl: string
  readonly features: readonly string[]
}

5. Make Illegal States Unrepresentable

This is the single most valuable TypeScript pattern. Model your domain with discriminated unions so impossible states can't exist.

// Good — each state carries exactly the data it needs
type AsyncState<T> =
  | { status: "idle" }
  | { status: "loading"; requestId: string }
  | { status: "success"; data: T }
  | { status: "error"; error: Error }

// Bad — boolean soup, impossible combinations representable
interface AsyncState<T> {
  isLoading?: boolean
  isError?: boolean
  data?: T
  error?: Error
  requestId?: string
}

If you switch on a discriminant at runtime, your types should mirror that structure. Use never in the default to ensure exhaustive handling — the compiler catches missing cases:

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "rect"; width: number; height: number }

function assertNever(x: never): never {
  throw new Error(`Unexpected value: ${x}`)
}

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.radius ** 2
    case "rect": return s.width * s.height
    default: return assertNever(s) // compile error if a case is missing
  }
}

Use this for: request states, auth states, form steps, permissions, payment states, message types — anything with distinct modes.

6. Parse at the Boundary

Validate and parse data when it enters your system. After that, trust the types. Don't scatter validation checks through business logic.

// Parse once at the boundary
function parseUser(data: unknown): User {
  if (!isObject(data)) throw new ParseError("expected object")
  const name = parseString(data.name, "name")
  const email = parseEmail(data.email)
  const age = parseAge(data.age)
  return { name, email, age }
}

// Business logic trusts the types — no re-validation
function greetUser(user: User): string {
  return `Hello, ${user.name}!`
}

Strengthen inputs, don't weaken outputs. If a function needs a non-empty array, require [T,...T[]] instead of accepting T[] and returning T | undefined.

// Prefer this — caller proves the precondition
function first<T>(list: [T, ...T[]]): T {
  return list[0]
}

// Over this — pushes uncertainty downstream
function first<T>(list: T[]): T | undefined {
  return list[0]
}

Branded Types

When you can't make an illegal state structurally impossible, use branded types with constructors:

type EmailAddress = string & { readonly __brand: "EmailAddress" }
type UserId = string & { readonly __brand: "UserId" }

function EmailAddress(input: string): EmailAddress {
  if (!input.includes("@")) throw new Error(`Invalid email: ${input}`)
  return input as EmailAddress
}

function UserId(input: string): UserId {
  if (!input.trim()) throw new Error("UserId cannot be empty")
  return input as UserId
}

// Now these are distinct types — can't accidentally swap them
function sendEmail(to: EmailAddress, body: string): void { /* ... */ }

7. Types: Precise but Simple

Make types tight — describe exactly what's possible, nothing more. But don't over-engineer the type system. If a type is hard to read, simplify it.

// Good — narrow string literals
type Method = "GET" | "POST" | "PUT" | "DELETE"
type Status = "active" | "inactive" | "pending"

// Good — satisfies preserves literal types while validating
const routes = {
  home: "/",
  about: "/about",
  user: "/user/:id",
} satisfies Record<string, string>

// Good — simple generics with clear constraints
function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
  const result = {} as Pick<T, K>
  for (const key of keys) result[key] = obj[key]
  return result
}

// Bad — type gymnastics that nobody can read
type DeepPartialConditionalMappedInferredNested<T> = ...

Default to type. Use interface when you need extends — it creates cached, flat object types that the compiler checks faster than & intersections. Avoid interface as a default because declaration merging (two interfaces with the same name silently merge) causes surprising bugs.

// type by default — for objects, unions, aliases, computed types
type User = {
  id: UserId
  name: string
  email: EmailAddress
  status: Status
}

type AsyncResult<T> = AsyncState<T>
type UserInput = Omit<User, "id">
type Handler = (req: Request) => Promise<Response>

// interface when you need extends — faster than & intersections
interface HttpError extends Error {
  status: number
  body: unknown
}

Use unknown over any. Narrow with type guards:

// Type predicates — narrow in .filter(), if blocks, etc.
function isString(val: unknown): val is string {
  return typeof val === "string"
}
const strings = mixed.filter(isString) // string[]

// Assertion functions — narrow or throw
function assertDefined<T>(val: T | undefined, msg: string): asserts val is T {
  if (val === undefined) throw new Error(msg)
}

8. Factory Functions by Default, Classes When Earned

Use factory functions with closures for configurable, composable objects. Reserve classes for: wrapping resources (DB connections, WebSocket, streams), fluent/chainable APIs (builders, schema validators like Zod), and Disposable objects used with using.

// Factory — simple, composable, no `this` headaches
function createFetcher(defaults: FetchOptions = {}) {
  async function request<T>(url: string, opts: FetchOptions = {}): Promise<T> {
    const merged = { ...defaults, ...opts }
    const res = await fetch(url, merged)
    if (!res.ok) throw new HttpError(res.status, await res.text())
    return res.json()
  }

  // Composable — create specialized fetchers
  request.withAuth = (token: string) =>
    createFetcher({ ...defaults, headers: { ...defaults.headers, Authorization: `Bearer ${token}` } })

  return request
}

const api = createFetcher({ baseUrl: "https://api.example.com" })
const authed = api.withAuth(token)

Identity Functions for Type Inference

Functions that return their argument unchanged — their only job is type inference:

function defineConfig<const T extends AppConfig>(config: T): T {
  return config
}

// The `const` modifier preserves literal types
const config = defineConfig({
  routes: ["/api/users", "/api/posts"],
  features: ["auth", "billing"],
})
// Type preserves the literal string arrays, not just string[]

9. Useful Patterns

Result Type (When Appropriate)

For expected failures where you want the caller to handle both paths explicitly. Don't use this everywhere — throw is fine for truly exceptional errors.

type Result<T, E = Error> =
  | { ok: true; value: T }
  | { ok: false; error: E }

function ok<T>(value: T): Result<T, never> {
  return { ok: true, value }
}

function err<E>(error: E): Result<never, E> {
  return { ok: false, error }
}

function parseConfig(raw: string): Result<Config, string> {
  try {
    const parsed = JSON.parse(raw)
    if (!parsed.host) return err("missing host")
    return ok(parsed as Config)
  } catch {
    return err("invalid JSON")
  }
}

Error Handling

Always type catch block errors as unknown, then narrow. Use Error.cause for chaining context through layers.

try {
  await fetchData()
} catch (err) {
  if (err instanceof Error) {
    throw new Error("Failed to load data", { cause: err })
  }
  throw err
}

Use Result types for expected failures (Section 9 above). Use throw for truly unexpected errors. Don't mix — pick one strategy per boundary.

Resolvable Values

One type for lazy/async/sync values — useful for config, subcommands, anything expensive:

type Resolvable<T> = T | Promise<T> | (() => T) | (() => Promise<T>)

async function resolve<T>(input: Resolvable<T>): Promise<T> {
  return typeof input === "function" ? (input as Function)() : input
}

10. Common Gotchas

Concrete pitfalls that cause runtime bugs despite passing type checks:

  • Object.keys() returns string[], not (keyof T)[]. TypeScript can't guarantee an object doesn't have extra keys at runtime. Cast explicitly when safe: Object.keys(obj) as Array<keyof typeof obj>.
  • .filter() doesn't narrow without a type predicate. Use .filter((x): x is T => x!== null) instead of .filter(x => x!== null).
  • Catch blocks: errors are unknown, not Error. Always narrow: catch (err) {if (err instanceof Error)...}.
  • {} matches any non-nullish value — including strings, numbers, and booleans. Use Record<string, unknown> for "some object" and unknown for "anything."
  • Type widening in conditionals: cond? "a": "b" infers as string, not "a" | "b". Use as const on the branches if you need literals.
  • Method syntax is bivariant: {compare(a: T): number} skips contravariance checks. Use function property syntax {compare: (a: T) => number} for type safety under strictFunctionTypes.

What NOT to Do

  • No enum — use union types or as const objects. Enums emit runtime code (non-erasable syntax), break Node's native TS support, and conflict with the "types as comments" future. TS 5.8's --erasableSyntaxOnly flag officially marks them as discouraged.
  • No namespace — use modules. Also non-erasable.
  • No I prefix on interfaces — just name the thing.
  • No FP ceremony or jargon — no monads, functors, or applicatives by name. But use practical FP patterns: Result types, pipe composition, exhaustive matching (see ts-pattern).
  • No unnecessary abstraction — three similar lines beats a premature createGenericHandler.
  • No any — use unknown and narrow, or fix the type.
  • No barrel files with circular re-exports — they explode module graphs, kill tree-shaking, and slow bundlers/test runners. One barrel at a package root is fine; barrels in every subdirectory are not.
  • No npm packages for 10 lines of code — inline tiny utils. (Zod, Hono, ts-pattern all ship zero dependencies.)
  • No unsanitized user input in SQL queries, HTML output, shell commands, or file paths. AI-generated code contains security vulnerabilities ~40% of the time. Validate and sanitize at every system boundary.

Style

  • const everywhere. let only for genuine reassignment.
  • type by default. interface only for extends. (See Section 7.)
  • Declare return types on top-level exported functions — helps AI assistants, compilation performance, and API clarity. Skip for JSX components.
  • Destructure in params when it helps: ({id, name}: User) =>...
  • Optional chaining and nullish coalescing: user?.address?.city?? "Unknown"
  • function keyword for named, exported functions. Arrows for inline callbacks and short helpers.
  • Trailing commas.
  • Template literals over string concatenation.
  • as const to preserve literal types.
  • satisfies to validate shape while preserving inference.
  • Enable noUncheckedIndexedAccess — makes array/object index access return T | undefined, catching unsafe assumptions like arr[0] or env.NODE_ENV.
  • Consider --erasableSyntaxOnly — disables enums, namespaces, and parameter properties. Aligns with Node's native TS support and the "types as comments" TC39 proposal.

For modern TypeScript features (using, NoInfer, const type params), see references/modern-features.md. For compilation performance tips, see references/performance.md. For patterns from top codebases (Zod, tRPC, Hono, TanStack), see references/patterns-in-the-wild.md.

平台分布

Codex

34.63%
按下载量换算61

Claude

31.97%
按下载量换算56

Cursor

19%
按下载量换算33

Gemini CLI

8.6%
按下载量换算15

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills