Skip to content

Commit

Permalink
Add types for function-partial (#437)
Browse files Browse the repository at this point in the history
  • Loading branch information
Masa-Shin authored Apr 9, 2022
1 parent 99136a1 commit 5fbafc4
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
19 changes: 19 additions & 0 deletions packages/function-partial/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// https://github.com/ronami/meta-typing/blob/master/src/tail/index.d.ts
type Tail<T extends Array<any>> =
((...t: T) => void) extends (h: any, ...rest: infer R) => void ? R : never;

/**
* Return a list of Args such that the corresponding value is undefined.
* @example PartialArgs<[number, string, boolean], [number, undefined, undefined]> equals to [string, boolean]
* @example PartialArgs<[number, string, ...boolean[]], [undefined, string]>
* equals to [number, ...boolean[]]
*/
type PartialArgs<Args extends any[], Values extends any[], Output extends any[] = []>
= [] extends Values
? [...Output, ...Args]
: undefined extends Values[0]
? PartialArgs<Tail<Args>, Tail<Values>, [...Output, Args[0]]>
: PartialArgs<Tail<Args>, Tail<Values>, Output>

export function partial<Values extends any[], F extends (...args: any) => any>(func: F, ...args: Values)
: (...args: PartialArgs<Parameters<F>, Values>) => ReturnType<F>
106 changes: 106 additions & 0 deletions packages/function-partial/index.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { partial } from './index';

// Case 1) one aurgument.
const sqrt = partial(Math.sqrt)
sqrt(16)

// @ts-expect-error
sqrt()
// @ts-expect-error
sqrt(2, 2)
// @ts-expect-error
sqrt(true)

const sqrtOf16 = partial(Math.sqrt, 16)
sqrtOf16()

// @ts-expect-error
sqrtOf16(16)

// Case 2) Two arguments.
const repeat = (str: string, n: number) => {
return str.repeat(n)
}

const anotherRepeat = partial(repeat)
anotherRepeat("a", 2)

// @ts-expect-error
anotherRepeat()
// @ts-expect-error
anotherRepeat("a")
// @ts-expect-error
anotherRepeat(2)
// @ts-expect-error
anotherRepeat(2, "a")

const repeatHello = partial(repeat, "hello, ")
repeatHello(10)

// @ts-expect-error
repeatHello()
// @ts-expect-error
repeatHello([])

const repeat3Times = partial(repeat, undefined, 3)
repeat3Times('hello, ')

// @ts-expect-error
repeat3Times()
// @ts-expect-error
repeat3Times({})

const repeatHello3Times = partial(repeat, "hello, ", 3)
repeatHello3Times()

// @ts-expect-error
repeatHello3Times(1, 2, 3)

// Case 3) three arguments.
const getFormattedPrice = (amount: number, unit: string, includeTax: boolean) => {
const tax = includeTax ? 1.1 : 1
return `${unit}${amount * tax}`
}

const anotherGetFormattedPrice = partial(getFormattedPrice)
anotherGetFormattedPrice(100, "$", true)

// @ts-expect-error
anotherGetFormattedPrice({})

const getFormattedPriceWithTax = partial(getFormattedPrice, undefined, undefined, true)
getFormattedPriceWithTax(100, "€")

const getFormattedPriceInUS = partial(getFormattedPrice, undefined, "$", undefined)
getFormattedPriceInUS(100, false)

const getFormattedCookiePrice = partial(getFormattedPrice, 100, undefined, undefined)
getFormattedCookiePrice("$", false)

const getFormattedCookiePriceInUS = partial(getFormattedPrice, 100, "$", undefined)
getFormattedCookiePriceInUS(true)

const getFormattedCookiePriceWithoutTax = partial(getFormattedPrice, 100, undefined, false)
getFormattedCookiePriceWithoutTax("¥")

const getFormattedPriceWithTaxInUS = partial(getFormattedPrice, undefined, "$", true)
getFormattedPriceWithTaxInUS(10000)

const getFormattedCookiePriceWithTaxInUS = partial(getFormattedPrice, 100, "$", true)
getFormattedCookiePriceWithTaxInUS()

// Case 4) arbitrarily many arguments.
const consoleLog = partial(console.log)
consoleLog("hello", ", ", "world")

const logHello = partial(console.log, "Hello")
logHello()

const logHelloWorld = partial(console.log, "Hello", ", ", "world")
logHelloWorld()

const logGreetWorld = partial(console.log, undefined, ", ", "world")
logGreetWorld("Good Afternoon")

const logGreetToSomeone = partial(console.log, undefined, ", ")
logGreetToSomeone("Good Afternoon", "World", "!")
3 changes: 2 additions & 1 deletion packages/function-partial/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"default": "./index.mjs"
}
},
"types": "index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c"
Expand All @@ -26,4 +27,4 @@
"bugs": {
"url": "https://github.com/angus-c/just/issues"
}
}
}

0 comments on commit 5fbafc4

Please sign in to comment.