PHP's min in TypeScript

Rosetta Stone: lua/min · r/min

How to use

Install via yarn add locutus and import: import { min } from 'locutus/php/math/min'.

Or with CommonJS: const { min } = require('locutus/php/math/min')

Use a bundler that supports tree-shaking so you only ship the functions you actually use. Vite, webpack, Rollup, and Parcel all handle this. For server-side use this is less of a concern.

Examples

These examples are extracted from test cases that automatically verify our functions against their native counterparts.

#codeexpected result
1min(1, 3, 5, 6, 7)1
2min([2, 4, 5])2
3min(0, 'hello')0
4min('hello', 0)'hello'
5min(-1, 'hello')-1
6min([2, 4, 8], [2, 5, 7])[2, 4, 8]
7min({2:'two', 1:'one', 3:'three', 5:'five', 4:'four'})'five'
8min('one', 'two')'one'

Notes

  • Long code cause we’re aiming for maximum PHP compatibility

Here's what our current TypeScript equivalent to PHP's min looks like.

type PhpMinMaxScalar = string | number | boolean | null
type PhpMinMaxObject = { [key: string]: PhpMinMaxValue }
type PhpMinMaxValue = PhpMinMaxScalar | PhpMinMaxValue[] | PhpMinMaxObject

const isCollection = (value: PhpMinMaxValue): value is PhpMinMaxValue[] | PhpMinMaxObject =>
typeof value === 'object' && value !== null

const objectToArray = (value: PhpMinMaxValue[] | PhpMinMaxObject): PhpMinMaxValue[] => {
if (Array.isArray(value)) {
return value
}

const converted = Object.values(value).filter((item): item is PhpMinMaxValue => typeof item !== 'undefined')

return converted
}

const compareValues = (current: PhpMinMaxValue, next: PhpMinMaxValue): number => {
const currentNum = Number(current)
const nextNum = Number(next)

if (current === next) {
return 0
}

if (isCollection(current)) {
if (isCollection(next)) {
const currentArray = objectToArray(current)
const nextArray = objectToArray(next)

if (nextArray.length > currentArray.length) {
return 1
}
if (nextArray.length < currentArray.length) {
return -1
}

for (let index = 0; index < currentArray.length; index += 1) {
const currentItem = currentArray[index]
const nextItem = nextArray[index]
if (typeof currentItem === 'undefined' || typeof nextItem === 'undefined') {
continue
}
const comparison = compareValues(currentItem, nextItem)
if (comparison !== 0) {
return comparison
}
}

return 0
}

return -1
}

if (isCollection(next)) {
return 1
}

if (Number.isNaN(nextNum) && !Number.isNaN(currentNum)) {
if (current === 0) {
return 0
}
return currentNum < 0 ? 1 : -1
}

if (Number.isNaN(currentNum) && !Number.isNaN(nextNum)) {
if (next === 0) {
return 0
}
return nextNum > 0 ? 1 : -1
}

if (typeof current === 'string' && typeof next === 'string' && Number.isNaN(currentNum) && Number.isNaN(nextNum)) {
return next > current ? 1 : -1
}

return nextNum > currentNum ? 1 : -1
}

export function min(...args: PhpMinMaxValue[]): PhpMinMaxValue {
// discuss at: https://locutus.io/php/min/
// original by: Onno Marsman (https://twitter.com/onnomarsman)
// revised by: Onno Marsman (https://twitter.com/onnomarsman)
// improved by: Jack
// improved by: Thomas Hohn
// note 1: Long code cause we're aiming for maximum PHP compatibility
// example 1: min(1, 3, 5, 6, 7)
// returns 1: 1
// example 2: min([2, 4, 5])
// returns 2: 2
// example 3: min(0, 'hello')
// returns 3: 0
// example 4: min('hello', 0)
// returns 4: 'hello'
// example 5: min(-1, 'hello')
// returns 5: -1
// example 6: min([2, 4, 8], [2, 5, 7])
// returns 6: [2, 4, 8]
// example 7: min({2:'two', 1:'one', 3:'three', 5:'five', 4:'four'})
// returns 7: 'five'
// example 8: min('one', 'two')
// returns 8: 'one'

if (args.length === 0) {
throw new Error('At least one value should be passed to min()')
}

let values: PhpMinMaxValue[]

if (args.length === 1) {
const only = args[0]
if (typeof only === 'undefined' || !isCollection(only)) {
throw new Error('Wrong parameter count for min()')
}

values = objectToArray(only)

if (values.length === 0) {
throw new Error('Array must contain at least one element for min()')
}
} else {
values = args
}

const first = values[0]
if (typeof first === 'undefined') {
throw new Error('Array must contain at least one element for min()')
}

let result = first

for (let index = 1; index < values.length; index += 1) {
const candidate = values[index]
if (typeof candidate === 'undefined') {
continue
}
if (compareValues(result, candidate) === -1) {
result = candidate
}
}

return result
}

Improve this function

Locutus is a community effort following The McDonald's Theory: we ship first iterations, hoping others will improve them. If you see something that could be better, we'd love your contribution.

View on GitHub · Edit on GitHub · View Raw


« More PHP math functions


Star