typescript
1
总安装量
1
周安装量
#44631
全站排名
安装命令
npx skills add https://github.com/enact-on/super-ai-github --skill typescript
Agent 安装分布
cursor
1
claude-code
1
Skill 文档
TypeScript Skill
Comprehensive patterns and best practices for TypeScript development.
What I Know
Basic Types
Primitive Types
// Primitive types
let str: string = 'hello'
let num: number = 42
let bool: boolean = true
let nothing: null = null
let notDefined: undefined = undefined
// Arrays
let numbers: number[] = [1, 2, 3]
let strings: Array<string> = ['a', 'b', 'c']
// Tuples (fixed length arrays)
let tuple: [string, number] = ['hello', 42]
// Any (avoid when possible)
let anything: any = 'could be anything'
// Unknown (safer than any)
let value: unknown = 'safe but needs type check'
if (typeof value === 'string') {
console.log(value.toUpperCase())
}
// Void (no return value)
function log(message: string): void {
console.log(message)
}
// Never (never returns)
function throwError(message: string): never {
throw new Error(message)
}
Special Types
// Literal types
let direction: 'up' | 'down' | 'left' | 'right' = 'up'
// Nullable types
let name: string | null = null
// Optional properties
interface User {
id: number
name: string
age?: number // Optional
email: string | null // Nullable
}
// Type assertions (use carefully)
const value = 'hello' as string
const element = document.getElementById('app') as HTMLDivElement
// Non-null assertion (only when you're sure)
const length = value!.length
Interfaces vs Types
Interfaces
// Interface (best for objects, can be extended)
interface User {
id: number
name: string
}
interface User {
email: string // Declaration merging
}
interface Admin extends User {
permissions: string[]
}
Type Aliases
// Type alias (more flexible, can represent anything)
type User = {
id: number
name: string
}
// Union types
type Status = 'pending' | 'active' | 'inactive'
// Intersection types
type UserWithTimestamp = User & {
createdAt: Date
updatedAt: Date
}
// Conditional types
type NonNullable<T> = T extends null | undefined ? never : T
When to use which
- Use interfaces for object shapes that can be extended or merged
- Use types for unions, intersections, conditional types, and primitives
Functions
Type Annotations
// Function declaration
function add(a: number, b: number): number {
return a + b
}
// Arrow function
const multiply = (a: number, b: number): number => a * b
// Function type
type MathOperation = (a: number, b: number) => number
const operation: MathOperation = (a, b) => a + b
Function Overloads
// Function overloading
function process(input: string): string
function process(input: number): number
function process(input: string | number): string | number {
if (typeof input === 'string') {
return input.toUpperCase()
}
return input * 2
}
// Method overloads in interface
interface Document {
createElement(tagName: 'div'): HTMLDivElement
createElement(tagName: 'span'): HTMLSpanElement
createElement(tagName: string): HTMLElement
}
Rest Parameters
function sum(...numbers: number[]): number {
return numbers.reduce((a, b) => a + b, 0)
}
function logPair(first: string, ...rest: string[]) {
console.log(first, rest)
}
Generics
Basic Generics
// Generic function
function identity<T>(arg: T): T {
return arg
}
identity<string>('hello')
identity(42) // Type inferred
// Generic interface
interface Box<T> {
value: T
}
const stringBox: Box<string> = { value: 'hello' }
const numberBox: Box<number> = { value: 42 }
// Generic class
class Storage<T> {
private items: T[] = []
add(item: T): void {
this.items.push(item)
}
get(index: number): T | undefined {
return this.items[index]
}
}
const stringStorage = new Storage<string>()
stringStorage.add('hello')
Generic Constraints
// Constraining generic with extends
interface Lengthwise {
length: number
}
function logLength<T extends Lengthwise>(arg: T): void {
console.log(arg.length)
}
logLength('hello') // Works - string has length
logLength([1, 2, 3]) // Works - array has length
// logLength(42) // Error - number doesn't have length
// Using keyof
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key]
}
const user = { name: 'John', age: 30 }
getProperty(user, 'name') // Works
// getProperty(user, 'email') // Error
Utility Types with Generics
// Partial - make all properties optional
type PartialUser = Partial<User>
// Required - make all properties required
type RequiredUser = Required<Partial<User>>
// Pick - select specific properties
type UserName = Pick<User, 'name'>
// Omit - remove specific properties
type UserWithoutId = Omit<User, 'id'>
// Record - create object type
type UserMap = Record<string, User>
Advanced Types
Conditional Types
// Basic conditional type
type NonNullable<T> = T extends null | undefined ? never : T
// Nested conditional
type Response<T> = T extends string
? { message: T }
: T extends number
? { value: T }
: { data: T }
type StringResponse = Response<'hello'> // { message: 'hello' }
type NumberResponse = Response<42> // { value: 42 }
Mapped Types
// Mapped type
type Readonly<T> = {
readonly [P in keyof T]: T[P]
}
type Optional<T> = {
[P in keyof T]?: T[P]
}
// Template literal types
type EventName<T extends string> = `on${Capitalize<T>}`
type ClickEvent = EventName<'click'> // 'onClick'
// Key remapping
type Getters<T> = {
[P in keyof T as `get${Capitalize<P & string>}`]: () => T[P]
}
interface User {
name: string
age: number
}
type UserGetters = Getters<User>
// { getName: () => string; getAge: () => number }
Utility Types
// Built-in utility types
interface User {
id: number
name: string
email: string
age: number
}
// Partial - all optional
type PartialUser = Partial<User>
// Required - all required
type RequiredUser = Required<Partial<User>>
// Readonly - all readonly
type ReadonlyUser = Readonly<User>
// Pick - select keys
type UserName = Pick<User, 'name' | 'email'>
// Omit - remove keys
type UserWithoutEmail = Omit<User, 'email'>
// Record - construct type
type UserRecord = Record<string, User>
// Extract - extract from union
type Primitive = Extract<string | number | boolean, string | number>
// Exclude - exclude from union
type NotString = Exclude<string | number | boolean, string>
// ReturnType - get return type
type AddReturn = ReturnType<typeof add> // number
// Parameters - get parameter types
type AddParams = Parameters<typeof add> // [number, number]
// Awaited - unwrap promise type
type Data = Awaited<Promise<{ id: number }>> // { id: number }
Type Guards & Narrowing
typeof Type Guard
function process(value: string | number) {
if (typeof value === 'string') {
value.toUpperCase() // TypeScript knows it's string
} else {
value.toFixed(2) // TypeScript knows it's number
}
}
instanceof Type Guard
class Dog {
bark() { console.log('Woof!') }
}
class Cat {
meow() { console.log('Meow!') }
}
function makeSound(animal: Dog | Cat) {
if (animal instanceof Dog) {
animal.bark()
} else {
animal.meow()
}
}
in Operator
interface Bird {
fly(): void
layEggs(): void
}
interface Fish {
swim(): void
layEggs(): void
}
function move(animal: Bird | Fish) {
if ('fly' in animal) {
animal.fly()
} else {
animal.swim()
}
}
Discriminated Unions
interface SuccessResponse {
status: 'success'
data: { id: number; name: string }
}
interface ErrorResponse {
status: 'error'
error: { message: string; code: number }
}
type ApiResponse = SuccessResponse | ErrorResponse
function handleResponse(response: ApiResponse) {
if (response.status === 'success') {
response.data // TypeScript knows this exists
} else {
response.error // TypeScript knows this exists
}
}
Custom Type Guards
interface User {
name: string
email: string
}
function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'name' in value &&
'email' in value
)
}
function processValue(value: unknown) {
if (isUser(value)) {
console.log(value.email) // TypeScript knows it's User
}
}
Type Assertions vs Type Guards
// Type assertion (use sparingly)
const value = 'hello' as unknown as number // Dangerous!
// Type guard (preferred)
function isString(value: unknown): value is string {
return typeof value === 'string'
}
if (isString(value)) {
value.toUpperCase() // Safe
}
Declaration Files
.d.ts Files
// types/index.d.ts
declare module 'my-library' {
export interface Options {
debug?: boolean
timeout?: number
}
export function init(options?: Options): void
export function processData(input: string): Promise<string>
}
// Global augmentation
declare global {
interface Window {
myApp: {
version: string
config: Record<string, unknown>
}
}
}
export {} // Required for global augmentation in modules
Module Declaration
// For modules without types
declare module 'untyped-library' {
export default function anyThing(value: any): any
}
// For global libraries
declare namespace NodeJS {
interface ProcessEnv {
MY_CUSTOM_VAR: string
}
}
tsconfig.json
Recommended Configuration
{
"compilerOptions": {
// Language and Environment
"target": "ES2022",
"lib": ["ES2022"],
"jsx": "react-jsx",
"module": "ESNext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
// Type Checking
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUncheckedIndexedAccess": true,
// Emit
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
// Interop Constraints
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Common Pitfalls
- Using
anyâ Useunknownand type guards instead - Not using strict mode â Enable strict in tsconfig.json
- Ignoring type errors â Fix them properly with proper types
- Overusing type assertions â Prefer type guards
- Not typing props â Always type function parameters
- Forgetting null checks â Enable strictNullChecks
- Missing return types â Explicit return types help catch errors
Best Practices
- Enable strict mode â Catches many errors at compile time
- Avoid any â Use unknown and type narrowing
- Use type inference â Let TypeScript infer when possible
- Prefer interfaces for objects â Use type for unions and computed types
- Use generics â Write reusable, type-safe code
- Type guards â Narrow types safely instead of asserting
- Utility types â Leverage Partial, Pick, Omit, etc.
- Declaration files â Properly type external libraries
- Read-only â Use readonly and as const for immutable data
- Type-only imports â Use
import typefor type-only imports
Part of SuperAI GitHub – Centralized OpenCode Configuration