compose
組合多個函數,創建函數管道。
基礎用法
typescript
import { compose } from 'radash'
const addOne = (x: number) => x + 1
const double = (x: number) => x * 2
const square = (x: number) => x * x
const composed = compose(addOne, double, square)
const result = composed(3)
// 計算過程: square(3) = 9, double(9) = 18, addOne(18) = 19
console.log(result) // 19
語法
typescript
function compose<T extends any[], U>(
...fns: ((...args: T) => U)[]
): (...args: T) => U
參數
...fns
(function[]): 要組合的函數數組
返回值
返回一個組合後的函數,從右到左執行。
示例
基本函數組合
typescript
import { compose } from 'radash'
const toUpperCase = (str: string) => str.toUpperCase()
const addExclamation = (str: string) => str + '!'
const repeat = (str: string) => str + str
const shout = compose(addExclamation, toUpperCase, repeat)
const result = shout('hello')
// 計算過程: repeat('hello') = 'hellohello', toUpperCase('hellohello') = 'HELLOHELLO', addExclamation('HELLOHELLO') = 'HELLOHELLO!'
console.log(result) // 'HELLOHELLO!'
處理數組
typescript
import { compose } 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((acc, x) => acc + x, 0)
const processNumbers = compose(sum, double, filterEven)
const result = processNumbers([1, 2, 3, 4, 5, 6])
// 計算過程: filterEven([1,2,3,4,5,6]) = [2,4,6], double([2,4,6]) = [4,8,12], sum([4,8,12]) = 24
console.log(result) // 24
處理對象
typescript
import { compose } from 'radash'
const getUsers = (data: any) => data.users
const filterActive = (users: any[]) => users.filter(user => user.active)
const mapNames = (users: any[]) => users.map(user => user.name)
const joinNames = (names: string[]) => names.join(', ')
const getActiveUserNames = compose(joinNames, mapNames, filterActive, getUsers)
const data = {
users: [
{ id: 1, name: 'Alice', active: true },
{ id: 2, name: 'Bob', active: false },
{ id: 3, name: 'Charlie', active: true },
{ id: 4, name: 'Diana', active: true }
]
}
const result = getActiveUserNames(data)
console.log(result) // 'Alice, Charlie, Diana'
處理字符串
typescript
import { compose } from 'radash'
const trim = (str: string) => str.trim()
const toLowerCase = (str: string) => str.toLowerCase()
const replaceSpaces = (str: string) => str.replace(/\s+/g, '-')
const addPrefix = (str: string) => `slug-${str}`
const createSlug = compose(addPrefix, replaceSpaces, toLowerCase, trim)
const result = createSlug(' Hello World ')
// 計算過程: trim(' Hello World ') = 'Hello World', toLowerCase('Hello World') = 'hello world', replaceSpaces('hello world') = 'hello-world', addPrefix('hello-world') = 'slug-hello-world'
console.log(result) // 'slug-hello-world'
處理數字
typescript
import { compose } from 'radash'
const add = (a: number) => (b: number) => a + b
const multiply = (a: number) => (b: number) => a * b
const square = (x: number) => x * x
const complexCalculation = compose(
square,
multiply(3),
add(5)
)
const result = complexCalculation(2)
// 計算過程: add(5)(2) = 7, multiply(3)(7) = 21, square(21) = 441
console.log(result) // 441
處理類型轉換
typescript
import { compose } from 'radash'
const parseNumber = (str: string) => parseInt(str, 10)
const addTen = (num: number) => num + 10
const double = (num: number) => num * 2
const toString = (num: number) => num.toString()
const processString = compose(toString, double, addTen, parseNumber)
const result = processString('15')
// 計算過程: parseNumber('15') = 15, addTen(15) = 25, double(25) = 50, toString(50) = '50'
console.log(result) // '50'
處理驗證和轉換
typescript
import { compose } from 'radash'
const validateEmail = (email: string) => {
if (!email.includes('@')) {
throw new Error('Invalid email')
}
return email
}
const normalizeEmail = (email: string) => email.toLowerCase().trim()
const addDomain = (email: string) => email.includes('@') ? email : email + '@example.com'
const processEmail = compose(addDomain, normalizeEmail, validateEmail)
try {
const result = processEmail(' USER@EXAMPLE.COM ')
console.log(result) // 'user@example.com'
} catch (error) {
console.error('Error:', error.message)
}
處理異步函數
typescript
import { compose } from 'radash'
const fetchUser = async (id: number) => {
const response = await fetch(`/api/users/${id}`)
return response.json()
}
const extractName = (user: any) => user.name
const toUpperCase = (name: string) => name.toUpperCase()
const getUserName = compose(toUpperCase, extractName, fetchUser)
// 注意:由於fetchUser是異步的,這個組合函數也會返回Promise
const result = await getUserName(1)
console.log(result) // 'ALICE'
處理條件邏輯
typescript
import { compose } from 'radash'
const isEven = (num: number) => num % 2 === 0
const double = (num: number) => num * 2
const addOne = (num: number) => num + 1
const processNumber = compose(
(num: number) => isEven(num) ? double(num) : addOne(num),
(num: number) => num * 3
)
console.log(processNumber(4)) // 24 (4是偶數,double(4)=8, 8*3=24)
console.log(processNumber(5)) // 18 (5是奇數,addOne(5)=6, 6*3=18)
處理錯誤處理
typescript
import { compose } from 'radash'
const safeParse = (str: string) => {
try {
return JSON.parse(str)
} catch {
return null
}
}
const extractName = (data: any) => data?.name || 'Unknown'
const toUpperCase = (name: string) => name.toUpperCase()
const processData = compose(toUpperCase, extractName, safeParse)
console.log(processData('{"name": "alice"}')) // 'ALICE'
console.log(processData('invalid json')) // 'UNKNOWN'
處理管道操作
typescript
import { compose } from 'radash'
const filterNumbers = (arr: any[]) => arr.filter(x => typeof x === 'number')
const double = (arr: number[]) => arr.map(x => x * 2)
const sum = (arr: number[]) => arr.reduce((acc, x) => acc + x, 0)
const formatResult = (num: number) => `Total: ${num}`
const processArray = compose(formatResult, sum, double, filterNumbers)
const mixedArray = [1, 'hello', 2, 'world', 3, true, 4]
const result = processArray(mixedArray)
// 計算過程: filterNumbers([1,'hello',2,'world',3,true,4]) = [1,2,3,4], double([1,2,3,4]) = [2,4,6,8], sum([2,4,6,8]) = 20, formatResult(20) = 'Total: 20'
console.log(result) // 'Total: 20'
處理復雜對象轉換
typescript
import { compose } from 'radash'
interface User {
id: number
name: string
email: string
age: number
}
const getUsers = (data: any) => data.users || []
const filterAdults = (users: User[]) => users.filter(user => user.age >= 18)
const mapNames = (users: User[]) => users.map(user => user.name)
const sortNames = (names: string[]) => names.sort()
const joinNames = (names: string[]) => names.join(', ')
const getAdultUserNames = compose(joinNames, sortNames, mapNames, filterAdults, getUsers)
const data = {
users: [
{ id: 1, name: 'Alice', email: 'alice@example.com', age: 25 },
{ id: 2, name: 'Bob', email: 'bob@example.com', age: 16 },
{ id: 3, name: 'Charlie', email: 'charlie@example.com', age: 30 },
{ id: 4, name: 'Diana', email: 'diana@example.com', age: 22 }
]
}
const result = getAdultUserNames(data)
console.log(result) // 'Alice, Charlie, Diana'
處理數學計算
typescript
import { compose } from 'radash'
const add = (a: number) => (b: number) => a + b
const multiply = (a: number) => (b: number) => a * b
const subtract = (a: number) => (b: number) => b - a
const square = (x: number) => x * x
const complexMath = compose(
square,
multiply(2),
add(10),
subtract(5)
)
const result = complexMath(3)
// 計算過程: subtract(5)(3) = -2, add(10)(-2) = 8, multiply(2)(8) = 16, square(16) = 256
console.log(result) // 256
注意事項
- 執行順序: 函數從右到左執行
- 類型安全: 確保函數參數和返回值類型匹配
- 性能: 組合函數會創建新的函數,注意內存使用
- 調試: 組合函數可能難以調試,建議添加日志
- 錯誤處理: 確保中間函數能正確處理錯誤
與其他方法的區別
pipe()
: 從左到右執行函數compose()
: 從右到左執行函數- 手動調用: 需要嵌套函數調用
實際應用場景
- 數據處理: 組合多個數據轉換步驟
- 字符串處理: 組合多個字符串操作
- 數學計算: 組合多個數學運算
- 驗證邏輯: 組合多個驗證步驟
- 格式化: 組合多個格式化操作