UPDATE January 30 2022
There is much easier and less verbose way to do it:
type Json =
| null
| string
| boolean
| number
| { [prop: string]: Json }
| Array<Json>
function array<
Elem,
First extends Elem[],
>(x: [...First], y: [...First]) {
}
/**
* Passed
*/
{
const _ = array([1, 2, 3], [1, 1, 1]) // ok
const __ = array(['a', 'b', 'c'], ['x', 'x', 'x']) // ok
}
/**
* Failed
*/
{
const __ = array([1, 2, 3], [1, 1, 1, 1]) //expected error
const ___ = array([1, 2, 3], ['a', 'b', 'c']) //expected error
const ____ = array([1], []) //expected error
const _____ = array([], [1]) //expected error
}
Playground
Here you can find very similar answer
Here you can find more information about inference on function arguments
TOOO VERBOSE AND UNEFFECTIVE WAY
Here you have:
type ArrayElement = number;
type Array1D = ReadonlyArray<ArrayElement>;
type MutableLength = unknown[]["length"]; // number
export type Length<T extends ReadonlyArray<any>> = T extends { length: infer L }
? MutableLength extends L
? MutableLength
: L
: MutableLength;
type CompareLength<
X extends ReadonlyArray<any>,
Y extends ReadonlyArray<any>
> = MutableLength extends Length<X>
? false
: MutableLength extends Length<Y>
? false
: Length<X> extends Length<Y>
? true
: false;
type CompareType<
X extends ReadonlyArray<any>,
Y extends ReadonlyArray<any>
> = X[number] extends Y[number] ? true:false
function array<
X extends Array1D,
Y extends {
0: Array1D
}[CompareLength<X,Y> extends true? CompareType<X,Y> extends true ?0 : never:never],
>(x: X, y: Y) {
}
const result = array([1, 2, 3] as const, [1, 2, 3] as const) // ok
const result2 = array([1, 2, 3] as const, [1, 2, '3'] as const) // error
const result3 = array([1, 2, 3] as const, [1, 2] as const) // error
const result4 = array([1, 2, 3] as const, [] as const) // error
const result5 = array([1, 2, 3] as const, []) // error
const result6 = array([], []) // error, because arrays are mutable. TS is unable to find out the length
Playground
This is my article, here you can find more explanations
Please keep in mind, you should operate only on readonly arrays.