Similar to as javascript array.

But you would need to specify the types of the parameters and also a return type. Yes you could configure your setup to not care about these things, but then that would defeat the object of using typescript.

export function shuffle<T>(array: T[]): T[] {
    let currentIndex = array.length,  randomIndex;

    // While there remain elements to shuffle.
    while (currentIndex != 0) {
  
      // Pick a remaining element.
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex--;
  
      // And swap it with the current element.
      [array[currentIndex], array[randomIndex]] = [
        array[randomIndex], array[currentIndex]];
    }
  
    return array;
};

You can get different options of shuffle from this question.

Answer from Sergii Rudenko on Stack Overflow
🌐
freeCodeCamp
freecodecamp.org › news › how-to-shuffle-an-array-of-items-using-javascript-or-typescript
How to Shuffle an Array of Items Using JavaScript or TypeScript
June 5, 2023 - Examples of floating-point numbers include 3.14, -0.5, 1.0, 2.71828, and so on. By subtracting 0.5 from the result of Math.random(), you introduce a random value between -0.5 and 0.5. This random value will cause the comparison function to return negative, positive, or zero values in a random manner for different pairs of elements. Consequently, the sort() method shuffles the array randomly.
🌐
DevGenius
blog.devgenius.io › mastering-array-shuffling-in-typescript-techniques-and-examples-7cd5eef0eb1e
Mastering Array Shuffling in TypeScript: Techniques and Examples | by Popa Vlad | Dev Genius
March 6, 2025 - Here’s an implementation of the ... } return array; } // Example usage: const items = [1, 2, 3, 4, 5]; const shuffledItems = shuffleArray(items); console.log(shuffledItems);...
🌐
Quora
quora.com › How-do-you-shuffle-an-array-of-items-using-JavaScript-or-TypeScript
How to shuffle an array of items using JavaScript or TypeScript - Quora
... If memory is not a problem, use two arrays, one filled with random numbers, sort it. With each swap, swap the elements in the array you wanted randomized. When the sorting is done, the other array is shuffled.
🌐
DeveloperMemos
developermemos.com › posts › shuffle-list-typescript
Shuffling a List with TypeScript | DeveloperMemos
August 27, 2023 - Finally, it swaps the current element with the element at index j. Another approach to shuffle a list in TypeScript is by using the sort method with a custom random comparator. The idea is to compare two elements randomly, causing the sort algorithm ...
🌐
JavaScript.info
javascript.info › tutorial › the javascript language › data types › array methods
Shuffle an array
The idea is to walk the array in ... later chapters // same can be written as: // let t = array[i]; array[i] = array[j]; array[j] = t [array[i], array[j]] = [array[j], array[i]]; } }...
🌐
Decipher
decipher.dev › shuffle
shuffle | 30 Seconds of Typescript - Decipher.dev
Use the Fisher-Yates algorithm to reorder the elements of the array. typescript · const shuffle = ([...arr]) => { let m = arr.length; while (m) { const i = Math.floor(Math.random() * m--); [arr[m], arr[i]] = [arr[i], arr[m]]; } return arr; }; ...
🌐
Bomberbot
bomberbot.com › typescript › how-to-shuffle-an-array-of-items-using-javascript-or-typescript
How to Shuffle an Array of Items Using JavaScript or TypeScript - Bomberbot
May 14, 2025 - Shuffling arrays is a fundamental task that every developer should know how to do efficiently and correctly. The Fisher-Yates shuffle is the gold standard due to its simplicity, efficiency, and unbiased shuffling. By understanding the underlying principles and trade-offs of different shuffling techniques, you can choose the most appropriate method for your specific use case. Whether you‘re working with JavaScript or TypeScript, the concepts and code samples provided in this article will help you confidently shuffle arrays in your own projects.
Find elsewhere
🌐
Python Examples
pythonexamples.org › typescript › how-to-shuffle-an-array
How to Shuffle an Array in TypeScript
function shuffleArray<T>(array: T[]): T[] { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; } const intArray: number[] = [1, 2, 3, 4, 5]; const shuffledArray = shuffleArray(intArray); ...
🌐
GitBook
basarat.gitbook.io › algorithms › shuffling
Shuffling | Algorithms in TypeScript
December 31, 2019 - Remember random number generation ... O(1) ... function shuffleInPlace<T>(array: T[]): T[] { // if it's 1 or 0 items, just return if (array.length <= 1) return array; // For each index in array for (let i = 0; i < array.length; i++) { // choose a random not-yet-placed item to place there // must be an item AFTER the current item, because the stuff // before has all already been placed const randomChoiceIndex = getRandom(i, array.length - 1); ...
🌐
npm
npmjs.com › package › @types › shuffle-array
@types/shuffle-array - npm
declare namespace shuffleArray { /** * copy - Sets if should return a shuffled copy of the given array. By default it's a falsy value. * rng - Specifies a custom random number generator.
      » npm install @types/shuffle-array
    
🌐
GitHub
github.com › neo › shuffle.ts
GitHub - neo/shuffle.ts: Shuffle an Array in TypeScript
November 23, 2017 - Shuffle an Array in TypeScript · npm i shuffle.ts ·
Author   neo
🌐
egghead.io
egghead.io › lessons › typescript-shuffle-an-array
Shuffle an array | egghead.io
July 27, 2017 - In each iteration i, we simply put a random item from the unshuffled position into the ith position within the shuffled position. Hence, increasing the length of the shuffled position.
🌐
Webdevtutor
webdevtutor.net › blog › typescript-array-shuffle
Mastering Array Shuffling in TypeScript
function shuffleArray<T>(array: T[]): T[] { const shuffledArray = array.slice(); for (let i = shuffledArray.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]]; } return shuffledArray; } const myArray ...
🌐
npm
npmjs.com › package › array-shuffle
array-shuffle - npm
February 2, 2026 - This is useful for deterministic ... import {arrayToShuffled} from 'array-shuffle'; const randomNumberGenerator = () => 0; const deterministic = arrayToShuffled([1, 2, 3, 4, 5, 6], {randomNumberGenerator}); //=> [2, 3, 4, 5, 6, 1]...
      » npm install array-shuffle
    
Published   Feb 02, 2026
Version   4.1.0
Author   Sindre Sorhus
Top answer
1 of 2
1

Recursive conditional types and variadic tuple types make it possible, but still a bit hairy, to do the sort of type manipulation you're talking about.

I think the following is the same general approach that you take in your answer, although the exact details are a bit different. I tried to make the types as "simple" as I could, although I'll leave it up to others to judge how successful that endeavor was:


I'll define a type function called FirstHalf<T> that returns the first half of a tuple T. If T has an odd number of elements then FirstHalf<T> will end in the middle element as well. So FirstHalf<[1,2,3,4]> should be [1,2], and FirstHalf<[1,2,3,4,5]> should be [1,2,3]:

type FirstHalf<T extends any[]> = T extends [infer F, ...infer M, any] ?
    [F, ...FirstHalf<M>] : T

And then LastHalf<T> will return the last half of a tuple type T by producing the the complement of FirstHalf<T>. That means if there are an odd number of elements in T, the middle element will not be in LastHalf<T>. So LastHalf<[1,2,3,4]> should be [3,4], and LastHalf<[1,2,3,4,5]> should be [4,5]:

type LastHalf<T extends any[]> = T extends [...FirstHalf<T>, ...infer E] ? E : never;

Then, Interleave<T, U> will interleave the elements from T with elements from U, so Interleave<[1,2,3],["A","B","C"]> should be [1,"A",2,"B",3,"C"]. If either T or U has elements left they will just be at the end, so Interleave<[1,2],["A","B","C","D","E"]> should be [1,"A",2,"B","C","D","E"]:

type Interleave<T extends any[], U extends any[]> =
    T extends [infer H, ...infer R] ? [H, ...Interleave<U, R>] : U

(Note that this is achieved by switching the role of T and U in the recursive call.)

Finally, Shuffle<T> will split T into its FirstHalf and LastHalf and Interleaves the halves together:

type Shuffle<T extends any[]> = Interleave<FirstHalf<[...T]>, LastHalf<[...T]>>;   

I didn't change the implementation of your shuffle() function; yes, you need type assertions or the like to convince the compiler that the implementation is safe. There's almost no chance the compiler would be able to follow that any array manipulation will turn T into Shuffle<T>. In the following I use a single call-signature overloaded function to avoid needing assertions inside the body:

function shuffle<T extends readonly any[]>(array: T): Shuffle<[...T]>;
function shuffle(array: any[]) {
    if (array.length === 0 || array.length === 1) {
        return array.slice();
    }
    const rest = array.slice();
    const middle = rest.splice(Math.ceil(array.length / 2), 1)[0];
    const first = rest.shift();
    return [first, middle, ...shuffle(rest)];
};

And let's test it:

const shuffled = shuffle([1, 2, 3, 4, 5, 6, 7, 8] as const);
// const shuffled: [1, 5, 2, 6, 3, 7, 4, 8]
console.log(shuffled); // [1, 5, 2, 6, 3, 7, 4, 8]

const oddShuffled = shuffle([1, 2, 3, 4, 5, 6, 7] as const);
// const oddShuffled: [1, 5, 2, 6, 3, 7, 4]
console.log(oddShuffled); // [1, 5, 2, 6, 3, 7, 4] 

Yep, looks good!

Playground link to code

2 of 2
0

As promised, here's the solution I came up with.

type SplitEven<T extends readonly any[], Start extends any[] = [], End extends any[] = []> =
    T['length'] extends 0 | 1 ? [[...Start, ...T], End] :
    T extends readonly [infer S, ...infer M, infer E] ? SplitEven<M, [...Start, S], [E, ...End]> :
    never;

type Shuffle<T extends readonly any[]> =
    T['length'] extends 0 | 1
        ? T
        : SplitEven<T> extends infer A
            ? A extends readonly [readonly [infer AH, ...infer AR], readonly [infer BH, ...infer BR]]
                ? [AH, BH, ...Shuffle<[...AR, ...BR]>]
                : never
            : never;

function shuffle<T extends readonly any[]>(array: T): Shuffle<T> {
    if (array.length === 0 || array.length === 1) {
        return array.slice() as Shuffle<T>;
    }

    const rest = array.slice();
    const middle = rest.splice(Math.ceil(array.length / 2), 1)[0];
    const first = rest.shift();

    return [first, middle, ...shuffle(rest)] as Shuffle<T>;
}

const array = [1, 2, 3, 4, 5, 6, 7, 8] as const;
const shuffled = shuffle(array);

type Shuffled = typeof shuffled; // [1, 5, 2, 6, 3, 7, 4, 8]

console.log(shuffled);

TypeScript playground

Both the function and the type work with odd-length arrays, too.

The only thing left is figure out whether I can avoid the as Shuffle<T> in the return statements. I suspect the second one is beyond TSC's capability since it would need to know how rest, middle, and first were determined, but I'm surprised the first one wasn't inferred.