Skip to content

chain

將多個函數鏈接在一起,按順序執行。

語法

typescript
chain<T>(
  ...functions: ((value: T) => T)[]
): (value: T) => T

參數

  • ...functions (((value: T) => T)[]): 要鏈接的函數數組

返回值

  • (value: T) => T: 鏈接後的函數

示例

基本用法

typescript
import { chain } from 'radash'

const addOne = (x: number) => x + 1
const multiplyByTwo = (x: number) => x * 2
const square = (x: number) => x * x

const pipeline = chain(addOne, multiplyByTwo, square)

const result = pipeline(3)
// 步驟: 3 -> 4 -> 8 -> 64
// 結果: 64

字符串處理

typescript
import { chain } from 'radash'

const toUpperCase = (str: string) => str.toUpperCase()
const addExclamation = (str: string) => str + '!'
const repeat = (str: string) => str + str

const processString = chain(toUpperCase, addExclamation, repeat)

const result = processString('hello')
// 步驟: 'hello' -> 'HELLO' -> 'HELLO!' -> 'HELLO!HELLO!'
// 結果: 'HELLO!HELLO!'

數組處理

typescript
import { chain } from 'radash'

const filterEven = (arr: number[]) => arr.filter(x => x % 2 === 0)
const double = (arr: number[]) => arr.map(x => x * 2)
const sum = (arr: number[]) => arr.reduce((a, b) => a + b, 0)

const processArray = chain(filterEven, double, sum)

const result = processArray([1, 2, 3, 4, 5, 6])
// 步驟: [1,2,3,4,5,6] -> [2,4,6] -> [4,8,12] -> 24
// 結果: 24

對象處理

typescript
import { chain } from 'radash'

const addId = (obj: any) => ({ ...obj, id: Date.now() })
const addTimestamp = (obj: any) => ({ ...obj, timestamp: new Date().toISOString() })
const addStatus = (obj: any) => ({ ...obj, status: 'active' })

const processObject = chain(addId, addTimestamp, addStatus)

const result = processObject({ name: 'Alice', age: 25 })
// 結果: { name: 'Alice', age: 25, id: 1234567890, timestamp: '2023-01-01T00:00:00.000Z', status: 'active' }

類型轉換

typescript
import { chain } from 'radash'

const toString = (num: number) => num.toString()
const addPrefix = (str: string) => 'Number: ' + str
const toUpperCase = (str: string) => str.toUpperCase()

const processNumber = chain(toString, addPrefix, toUpperCase)

const result = processNumber(42)
// 步驟: 42 -> '42' -> 'Number: 42' -> 'NUMBER: 42'
// 結果: 'NUMBER: 42'

條件處理

typescript
import { chain } from 'radash'

const validateAge = (age: number) => {
  if (age < 0 || age > 120) {
    throw new Error('Invalid age')
  }
  return age
}

const categorizeAge = (age: number) => {
  if (age < 18) return 'minor'
  if (age < 65) return 'adult'
  return 'senior'
}

const addCategory = (category: string) => ({ category })

const processAge = chain(validateAge, categorizeAge, addCategory)

const result = processAge(25)
// 結果: { category: 'adult' }

錯誤處理

typescript
import { chain } from 'radash'

const safeDivide = (x: number) => {
  if (x === 0) throw new Error('Division by zero')
  return 100 / x
}

const addOne = (x: number) => x + 1
const multiplyByTwo = (x: number) => x * 2

const processNumber = chain(safeDivide, addOne, multiplyByTwo)

try {
  const result = processNumber(5)
  console.log(result) // 42
} catch (error) {
  console.error('Error:', error.message)
}

try {
  processNumber(0) // 拋出錯誤
} catch (error) {
  console.error('Error:', error.message) // 'Division by zero'
}

異步函數鏈

typescript
import { chain } from 'radash'

const fetchUser = async (id: number) => {
  const response = await fetch(`/api/users/${id}`)
  return response.json()
}

const addTimestamp = (user: any) => ({
  ...user,
  fetchedAt: new Date().toISOString()
})

const addStatus = (user: any) => ({
  ...user,
  status: user.active ? 'active' : 'inactive'
})

// 注意:異步函數需要特殊處理
const processUser = async (id: number) => {
  const user = await fetchUser(id)
  return chain(addTimestamp, addStatus)(user)
}

// 使用
processUser(123).then(result => {
  console.log(result)
})

數據驗證鏈

typescript
import { chain } from 'radash'

const validateEmail = (email: string) => {
  if (!email.includes('@')) {
    throw new Error('Invalid email format')
  }
  return email.toLowerCase()
}

const validateLength = (email: string) => {
  if (email.length < 5) {
    throw new Error('Email too short')
  }
  return email
}

const addDomain = (email: string) => {
  if (!email.includes('.')) {
    return email + '.com'
  }
  return email
}

const processEmail = chain(validateEmail, validateLength, addDomain)

try {
  const result = processEmail('user@example')
  console.log(result) // 'user@example.com'
} catch (error) {
  console.error('Validation error:', error.message)
}

配置處理

typescript
import { chain } from 'radash'

const setDefaults = (config: any) => ({
  port: 3000,
  host: 'localhost',
  debug: false,
  ...config
})

const validateConfig = (config: any) => {
  if (config.port < 1 || config.port > 65535) {
    throw new Error('Invalid port number')
  }
  return config
}

const addTimestamp = (config: any) => ({
  ...config,
  createdAt: new Date().toISOString()
})

const processConfig = chain(setDefaults, validateConfig, addTimestamp)

const result = processConfig({ port: 8080, debug: true })
// 結果: { port: 8080, host: 'localhost', debug: true, createdAt: '2023-01-01T00:00:00.000Z' }

文本處理管道

typescript
import { chain } from 'radash'

const trim = (str: string) => str.trim()
const toLowerCase = (str: string) => str.toLowerCase()
const removeSpecialChars = (str: string) => str.replace(/[^a-z0-9\s]/g, '')
const normalizeSpaces = (str: string) => str.replace(/\s+/g, ' ')

const normalizeText = chain(trim, toLowerCase, removeSpecialChars, normalizeSpaces)

const result = normalizeText('  Hello, World!  ')
// 步驟: '  Hello, World!  ' -> 'Hello, World!' -> 'hello, world!' -> 'hello world' -> 'hello world'
// 結果: 'hello world'

注意事項

  1. 函數順序: 函數按從左到右的順序執行
  2. 類型安全: 所有函數必須接受和返回相同類型
  3. 錯誤處理: 鏈中的任何函數拋出錯誤都會中斷執行
  4. 性能: 每個函數都會創建新的值,不會修改原值

與其他函數的區別

  • chain: 將多個函數鏈接在一起
  • compose: 從右到左組合函數
  • pipe: 從左到右組合函數
  • flow: 類似功能,但可能有不同的實現

性能

  • 時間復雜度: O(n),其中 n 是函數數量
  • 空間復雜度: O(n)
  • 適用場景: 數據處理管道、函數組合

Released under the MIT License.