@@ -2,183 +2,146 @@ import { AttemptResult, EventId, RankingType, formatCentiseconds } from '@wca/he
22
33/**
44 * Returns a copy of the object with the value at the specified path transformed by the update function.
5- *
6- * @param {Object } object
7- * @param {Array } propertyChain
8- * @param {Function } updater
9- * @returns {Object }
105 */
11- export const updateIn = ( object , [ property , ...properyChain ] : string [ ] , updater ) =>
6+ export const updateIn = < T > ( object : T , [ property , ...properyChain ] : string [ ] , updater : ( value : unknown ) => unknown ) : T =>
127 properyChain . length === 0
13- ? { ...object , [ property ] : updater ( object [ property ] ) }
8+ ? { ...object , [ property ] : updater ( ( object as Record < string , unknown > ) [ property ] ) }
149 : {
1510 ...object ,
16- [ property ] : updateIn ( object [ property ] , properyChain , updater ) ,
11+ [ property ] : updateIn ( ( object as Record < string , unknown > ) [ property ] , properyChain , updater ) ,
1712 } ;
1813
1914/**
2015 * Returns a copy of the object with the value at the specified path set to the given one.
21- *
22- * @param {Object } object
23- * @param {Array } propertyChain
24- * @param {* } value
25- * @returns {Object }
2616 */
27- export const setIn = ( object , properyChain , value ) => updateIn ( object , properyChain , ( ) => value ) ;
17+ export const setIn = < T > ( object : T , properyChain : string [ ] , value : unknown ) : T =>
18+ updateIn ( object , properyChain , ( ) => value ) ;
2819
2920/**
3021 * Returns a copy of the object with the value at the specified path merged with the given one.
31- *
32- * @param {Object } object
33- * @param {Array } propertyChain
34- * @param {Object } newValue
35- * @returns {Object }
3622 */
37- export const mergeIn = ( object , properyChain , newValue ) =>
23+ export const mergeIn = < T > ( object : T , properyChain : string [ ] , newValue : Record < string , unknown > ) : T =>
3824 updateIn ( object , properyChain , ( currentValue ) => ( {
39- ...currentValue ,
25+ ...( currentValue as Record < string , unknown > ) ,
4026 ...newValue ,
4127 } ) ) ;
4228
4329/**
4430 * Returns a copy of the object with the array at the specified path mapped with the given function.
45- *
46- * @param {Object } object
47- * @param {Array<string> } propertyChain
48- * @param {Object } mapper
49- * @returns {Object }
5031 */
51- export const mapIn = ( object , properyChain , mapper ) =>
52- updateIn ( object , properyChain , ( array ) => array && array . map ( mapper ) ) ;
32+ export const mapIn = < T > ( object : T , properyChain : string [ ] , mapper : ( item : unknown ) => unknown ) : T =>
33+ updateIn ( object , properyChain , ( array ) => ( array as unknown [ ] ) ? .map ( mapper ) ) ;
5334
5435/**
5536 * Returns object's value at the specified path or the default value if it doesn't exist.
56- *
57- * @param {Object } object
58- * @param {Array } propertyChain
59- * @param {* } defaultValue
60- * @returns {* }
6137 */
62- export const getIn = ( object , [ property , ...propertyChain ] : string [ ] , defaultValue = null ) =>
38+ export const getIn = ( object : Record < string , unknown > | null | undefined , [ property , ...propertyChain ] : string [ ] , defaultValue : unknown = null ) : unknown =>
6339 object
6440 ? propertyChain . length === 0
6541 ? object . hasOwnProperty ( property )
6642 ? object [ property ]
6743 : defaultValue
68- : getIn ( object [ property ] , propertyChain , defaultValue )
44+ : getIn ( object [ property ] as Record < string , unknown > , propertyChain , defaultValue )
6945 : defaultValue ;
7046
7147/**
7248 * Checks if the given value is an object.
73- *
74- * @param {* } value
75- * @returns {boolean }
7649 */
77- const isObject = ( obj ) => obj === Object ( obj ) ;
50+ const isObject = ( obj : unknown ) : obj is Record < string , unknown > => obj === Object ( obj ) ;
7851
7952/**
8053 * When given an object, deeply checks if it doesn't contain null values.
8154 * Otherwise, checks if the given value is not null.
82- *
83- * @param {* } value
84- * @returns {boolean }
8555 */
86- export const isPresentDeep = ( value ) =>
56+ export const isPresentDeep = ( value : unknown ) : boolean =>
8757 isObject ( value ) ? Object . values ( value ) . every ( isPresentDeep ) : value != null ;
8858
8959/**
9060 * Pluralizes a word according to the given number.
9161 * When no plural form given, uses singular form with an 's' appended.
92- *
93- * @param {number } count
94- * @param {string } singular
95- * @param {string } plural
96- * @returns {string }
9762 */
98- export const pluralize = ( count , singular , plural ) =>
63+ export const pluralize = ( count : number , singular : string , plural ?: string ) : string =>
9964 `${ count } ${ count === 1 ? singular : plural || singular + 's' } ` ;
10065
10166/**
10267 * Pluralizes a word according to the given number.
10368 * When no plural form given, uses singular form with an 's' appended.
104- *
105- * @param {number } count
106- * @param {string } singular
107- * @param {string } plural
108- * @returns {string }
10969 */
110- export const pluralizeWord = ( count , singular , plural ) =>
70+ export const pluralizeWord = ( count : number , singular : string , plural ?: string ) : string =>
11171 `${ count === 1 ? singular : plural || singular + 's' } ` ;
11272
11373/**
11474 * Returns a new array with items summing up to 1, preserving elements proportionality.
11575 * When the given array is empty, returns an empty array.
116- *
117- * @param {Array } arr
118- * @returns {Array }
11976 */
120- export const scaleToOne = ( arr ) => {
77+ export const scaleToOne = ( arr : number [ ] ) : number [ ] => {
12178 if ( arr . length === 0 ) return [ ] ;
12279 const arrSum = sum ( arr ) ;
12380 return arr . map ( ( x ) => ( arrSum !== 0 ? x / arrSum : 1 / arr . length ) ) ;
12481} ;
12582
12683/**
12784 * Applies the given function to the elements and returns the first truthy value of these calls.
128- *
129- * @param {Array } arr
130- * @returns {* }
13185 */
132- export const firstResult = ( arr , fn ) => arr . reduce ( ( result , x ) => result || fn ( x ) , null ) ;
86+ export const firstResult = < T , R > ( arr : T [ ] , fn : ( item : T ) => R ) : R | null =>
87+ arr . reduce ( ( result : R | null , x ) => result || fn ( x ) , null ) ;
13388
134- export const flatMap = ( arr , fn ) => arr . reduce ( ( xs , x ) => xs . concat ( fn ( x ) ) , [ ] ) ;
89+ export const flatMap = < T , R > ( arr : T [ ] , fn : ( item : T ) => R [ ] ) : R [ ] =>
90+ arr . reduce ( ( xs : R [ ] , x ) => xs . concat ( fn ( x ) ) , [ ] ) ;
13591
136- export const flatten = ( arr ) => arr . reduce ( ( xs , x ) => xs . concat ( x ) , [ ] ) ;
92+ export const flatten = < T > ( arr : T [ ] [ ] ) : T [ ] => arr . reduce ( ( xs , x ) => xs . concat ( x ) , [ ] ) ;
13793
13894/**
139- *
140- * @param {Array } arr - Array of elements
141- * @param {* } fn - returns a value to group by
142- * @returns
95+ * Groups array elements by a given function
14396 */
144- export const groupBy = ( arr , fn ) =>
145- arr . reduce ( ( obj , x ) => updateIn ( obj , [ fn ( x ) ] , ( xs ) => ( xs || [ ] ) . concat ( x ) ) , { } ) ;
97+ export const groupBy = < T , K extends string | number > ( arr : T [ ] , fn : ( item : T ) => K ) : Record < K , T [ ] > =>
98+ arr . reduce ( ( obj , x ) => updateIn ( obj , [ String ( fn ( x ) ) ] , ( xs ) => ( ( xs as T [ ] ) || [ ] ) . concat ( x ) ) , { } as Record < K , T [ ] > ) ;
14699
147- export const zip = ( ...arrs ) =>
100+ export const zip = < T > ( ...arrs : T [ ] [ ] ) : T [ ] [ ] =>
148101 arrs . length === 0 ? [ ] : arrs [ 0 ] . map ( ( _ , i ) => arrs . map ( ( arr ) => arr [ i ] ) ) ;
149102
150- export const findLast = ( arr , predicate ) =>
103+ export const findLast = < T > ( arr : T [ ] , predicate : ( item : T ) => boolean ) : T | undefined =>
151104 arr . reduceRight (
152105 ( found , x ) => ( found !== undefined ? found : predicate ( x ) ? x : undefined ) ,
153- undefined
106+ undefined as T | undefined
154107 ) ;
155108
156- export const intersection = ( xs , ys ) => xs . filter ( ( x ) => ys . includes ( x ) ) ;
109+ export const intersection = < T > ( xs : T [ ] , ys : T [ ] ) : T [ ] => xs . filter ( ( x ) => ys . includes ( x ) ) ;
157110
158- export const difference = ( xs , ys ) => xs . filter ( ( x ) => ! ys . includes ( x ) ) ;
111+ export const difference = < T > ( xs : T [ ] , ys : T [ ] ) : T [ ] => xs . filter ( ( x ) => ! ys . includes ( x ) ) ;
159112
160- export const partition = ( xs , fn ) => [ xs . filter ( fn ) , xs . filter ( ( x ) => ! fn ( x ) ) ] ;
113+ export const partition = < T > ( xs : T [ ] , fn : ( item : T ) => boolean ) : [ T [ ] , T [ ] ] =>
114+ [ xs . filter ( fn ) , xs . filter ( ( x ) => ! fn ( x ) ) ] ;
161115
162- const sortCompare = ( x , y ) => ( x < y ? - 1 : x > y ? 1 : 0 ) ;
116+ const sortCompare = ( x : unknown , y : unknown ) : number => ( x < y ? - 1 : x > y ? 1 : 0 ) ;
163117
164- export const sortBy = ( arr , fn ) => arr . slice ( ) . sort ( ( x , y ) => sortCompare ( fn ( x ) , fn ( y ) ) ) ;
118+ export const sortBy = < T > ( arr : T [ ] , fn : ( item : T ) => unknown ) : T [ ] =>
119+ arr . slice ( ) . sort ( ( x , y ) => sortCompare ( fn ( x ) , fn ( y ) ) ) ;
165120
166- export const sortByArray = ( arr , fn ) => {
121+ export const sortByArray = < T > ( arr : T [ ] , fn : ( item : T ) => unknown [ ] ) : T [ ] => {
167122 const values = new Map ( arr . map ( ( x ) => [ x , fn ( x ) ] ) ) ; /* Compute every value once. */
123+ const firstResult = < R > ( pairs : unknown [ ] [ ] , fn : ( pair : [ unknown , unknown ] ) => R | 0 ) : R | 0 => {
124+ for ( const pair of pairs ) {
125+ const result = fn ( pair as [ unknown , unknown ] ) ;
126+ if ( result !== 0 ) return result ;
127+ }
128+ return 0 ;
129+ } ;
168130 return arr
169131 . slice ( )
170- . sort ( ( x , y ) => firstResult ( zip ( values . get ( x ) , values . get ( y ) ) , ( [ a , b ] ) => sortCompare ( a , b ) ) ) ;
132+ . sort ( ( x , y ) => firstResult ( zip ( values . get ( x ) as unknown [ ] , values . get ( y ) as unknown [ ] ) , ( [ a , b ] ) => sortCompare ( a , b ) ) ) ;
171133} ;
172134
173- export const chunk = ( arr , size ) =>
135+ export const chunk = < T > ( arr : T [ ] , size : number ) : T [ ] [ ] =>
174136 arr . length <= size ? [ arr ] : [ arr . slice ( 0 , size ) , ...chunk ( arr . slice ( size ) , size ) ] ;
175137
176- export const times = ( n , fn ) => Array . from ( { length : n } , ( _ , index ) => fn ( index ) ) ;
138+ export const times = < T > ( n : number , fn : ( index : number ) => T ) : T [ ] =>
139+ Array . from ( { length : n } , ( _ , index ) => fn ( index ) ) ;
177140
178141export const uniq = < T > ( arr : T [ ] ) : T [ ] => [ ...new Set ( arr ) ] ;
179142
180- export const pick = ( obj , keys ) =>
181- keys . reduce ( ( newObj , key ) => ( { ...newObj , [ key ] : obj [ key ] } ) , { } ) ;
143+ export const pick = < T extends Record < string , unknown > > ( obj : T , keys : ( keyof T ) [ ] ) : Partial < T > =>
144+ keys . reduce ( ( newObj , key ) => ( { ...newObj , [ key ] : obj [ key ] } ) , { } as Partial < T > ) ;
182145
183146export const omit = < T extends object , K extends keyof T > ( obj : T , ...keys : K [ ] ) : Omit < T , K > => {
184147 const _ = { ...obj }
@@ -197,7 +160,7 @@ export const addMilliseconds = (isoString: string, milliseconds: number) =>
197160export const isoTimeDiff = ( first : string , second : string ) =>
198161 Math . abs ( new Date ( first ) . getTime ( ) - new Date ( second ) . getTime ( ) ) ;
199162
200- export const shortTime = ( isoString , timeZone = 'UTC' ) =>
163+ export const shortTime = ( isoString : string , timeZone = 'UTC' ) =>
201164 new Date ( isoString ) . toLocaleTimeString ( 'en-US' , {
202165 timeZone,
203166 hour : 'numeric' ,
0 commit comments