04484-medium-istuple

Back

// your answers
type IsTuple<T> = [T] extends [never] 
? false 
: T extends readonly unknown[]   
    ? number extends T['length']
      ? false
      : true
    : false

Solution by pea-sys #33072

// your answers
type IsTuple<T extends { length: number }> = [T] extends [never]
  ? false
  : T extends any[] | readonly any[]
    ? T['length'] extends number
      ? number extends T['length']
        ? false
        : true
      : false
    : false;

Solution by kakasoo #32688

type ReadonlyTuple<T extends readonly any[]> = T extends readonly []
	? readonly []
	: T extends readonly [infer Head]
	? readonly [Head]
	: T extends readonly [infer Head, ...infer Tail]
	? readonly [Head, ...ReadonlyTuple<Tail>]
	: never;

type TupleOrReadonlyTuple<T extends readonly any[]> = "push" extends keyof T ? [...ReadonlyTuple<T>] : ReadonlyTuple<T>;

type IsTuple<T> = [T] extends [never]
	? false
	: T extends ReadonlyArray<any>
	? T extends TupleOrReadonlyTuple<T>
		? true
		: false
	: false;

Solution by gasmg #32215

Just a different way of solution

type IsTuple<T> = 
    [T] extends [never] 
        ? false 
        : "length" extends keyof T
            ? number extends T["length"] 
                ? false 
                : number extends keyof T 
                    ? true 
                    : false 
            : false
;

Solution by RusJstudent #31687

type IsTuple<T> = [T] extends [never] ? false: T extends readonly unknown[] ? number extends T['length'] ? false:  true : false

Solution by Yoon-Hae-Min #30546

type TupleElement = number | string | boolean | symbol | bigint | object | undefined | null

type IsTuple<T> = 
  [T] extends [never] 
    ?
      false
    : T extends [] 
        ? 
          true 
          : T extends readonly [...any[]]
            ? 
              [] extends T
                ?
                  false
                : T[0] extends TupleElement
                    ?
                      true
                    : false
            : false

Solution by zhangqiangzgz #30198

// your answers

  // number extexts 1 ? false : true 
                          // 1 extends number ? true : false 
                            // tuple is fixed length 

type IsTuple<T> = [T] extends [never]? false : 
                      T extends readonly unknown[] ?
                           number extends T["length"] ? 
                              false : 
                              true :
                         false

Solution by kerolossamir165 #29041

type IsTuple<T> = [T] extends [never]
  ? false
  : T extends readonly unknown[]
  ? number extends T["length"]
    ? false
    : true
  : false;

Solution by DoubleWoodLin #28741

type Shift<T> = T extends [] ?  [] : T extends readonly [infer _, ...infer R] ? R : never;
type IsTuple<T> = Shift<T> extends never ? false : true;

Solution by breakinferno #28420

// 元组类型的 length 是数字字面量,而数组的 length 是 number。
type a = string[]["length"]; // number

type b = [string, string]["length"]; // 2

// 排除特殊情况,条件类型左边的裸类型如果是never,就会直接返回never
type IsTuple<T> = [T] extends [never]
  ? false
  : T extends readonly any[]
  ? number extends T["length"]
    ? false
    : true
  : false;

Solution by jiaowoxiaobala #27985

type IsTuple<T> = T extends readonly [] ? true : T extends readonly [infer C, ...infer K] ? true : false

Solution by HenrryShaw #27748

type IsTuple<T> = [T] extends [never] ? false : T extends readonly unknown[] ? number extends T['length'] ? false : true : false

Solution by jiechliu #27700

type IsTuple<T> = [T] extends [readonly [...infer R]] ? (number extends R['length'] ? false : true) : false;

Solution by rldnd #26971

type IsTuple<T extends readonly any[] | { length: number }> = 
  [T] extends [never] ? 
    false : 
    T extends readonly any[] ?
      number extends T['length'] ? 
        false : 
        true :
      false;

Solution by kakasoo #26511

type IsTuple<T> = [T] extends [never]
  ? false
  : T extends readonly unknown[]
    ? number extends T['length']
      ? false
      : true
    : false;

Solution by yungo1846 #25638

4484 - IsTuple

Determining whether an input is a tuple is a wild ride into the theory of TypeScript's type system. This is probably one of the most educational challenges to date. So many concepts are necessary to cover to arrive at some of the solutions. It's a valuable challenge, for sure!

🎥 Video Explanation

Release Date: 2023-03-09 19:00 UTC

IsTuple

🔢 Code

// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'

type A1 = IsTuple<[]>;
type B1 = true;
type C1 = Expect<Equal<A1, B1>>;

type A2 = IsTuple<[number]>;
type B2 = true;
type C2 = Expect<Equal<A2, B2>>;

type A3 = IsTuple<readonly [1]>;
type B3 = true;
type C3 = Expect<Equal<A3, B3>>;

type A4 = IsTuple<{ length: 1 }>;
type B4 = false;
type C4 = Expect<Equal<A4, B4>>;

type A5 = IsTuple<number[]>;
type B5 = false;
type C5 = Expect<Equal<A5, B5>>;

type A6 = IsTuple<never>;
type B6 = false;
type C6 = Expect<Equal<A6, B6>>;

// I added this case :)
type A7 = IsTuple<any>;
type B7 = false;
type C7 = Expect<Equal<A7, B7>>;

// ============= Your Code Here =============

// when doing `number extends T['length']`:
// - an array's "length" is `number`
// - a tuple's "length" is a specific number literal

type W = 1 extends 1 ? true : false; // true
type X = number extends number ? true : false; // true
type Y = number extends 1 ? true : false; // false
type Z = 1 extends number ? true : false; // true

type IsAny<T> = 1 extends T & 0 ? true : false;
type A = any & 0; // any
type B = never & 0; // never
type C = unknown & 0; // 0

/*
|     | [never] | never[] |
| --- | ------- | ------- |
| [T] | ✓ (0)   | ✓ (1)   |
| T[] | ✓ (2)   | ✓ (3)   |
*/
type IsNever0<T> = [T] extends [never] ? true : false;
type IsNever1<T> = [T] extends never[] ? true : false;
type IsNever2<T> = T[] extends [never] ? true : false;
type IsNever3<T> = T[] extends never[] ? true : false;

type IsNever<T> = [T] extends [never] ? true : false

type IsTuple<T> =
  true extends IsAny<T> | IsNever<T>
  ? false
  : T extends
      | readonly [infer _Head, ...infer _Tail]
      | readonly []
    ? true
    : false;

// ============== Alternatives ==============
// doesn't handle `any`
// type IsTuple<T> =
//   [T] extends [never] // is never
//   ? false
//   : T extends readonly [] // is empty tuple
//     ? true
//     : T extends readonly [infer _Head, ...infer _Tail]
//       ? true
//       : false

// type IsTuple<T> =
//   [T] extends [never]
//   ? false
//   : T extends readonly any[]
//     ? number extends T['length']
//       ? false
//       : true
//     : false;

// type IsTuple<T> =
//   [T] extends [never]
//   ? false
//   : T extends readonly unknown[]
//     ? number extends T["length"]
//       ? false
//       : true
//     : false;

// ================== NOPE ==================
// // doesn't handle `never`
// type IsTuple<T> =
//   T extends readonly any[]
//   ? number extends T['length']
//     ? false
//     : true
//   : false

➕ More Solutions

For more video solutions to other challenges: see the umbrella list! https://github.com/type-challenges/type-challenges/issues/21338

Solution by dimitropoulos #24328

type IsTuple<T> = [T] extends [never] 
? false 
: T extends readonly unknown[]   
    ? number extends T['length']
      ? false
      : true
    : false

Solution by NeylonR #24268

type IsTuple<T extends object> = [T] extends [never] ? false : T extends readonly any[] ? number extends T[`length`] ? false : true : false;

Solution by E-uler #23952

type IsTuple<T extends any[] | readonly any[]> =
  `${T["length"]}` extends `${infer F}${infer Rest}`
    ? F extends "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
      ? true
      : false
    : never;

Solution by ZegTsai #23030

type IsTuple<T> = [T] extends [never] ? false : T extends readonly any[] ?
number extends T['length'] ? false : true : false

Solution by snakeUni #22934

type IsTuple<T> = 
  [T] extends [never] 
  ? false 
  : T extends readonly any[]
    ? number extends T['length']
      ? false
      : true
    : T extends {length:number}
      ? false
      : true

Solution by Allengl #22849

// your answers
type IsTuple<T> = [T] extends [never] ? false: T extends readonly unknown[] ? number extends T['length'] ? false: true: false;

Solution by edisonLzy #22798

// your answers
type IsTuple<T> = [T] extends [never]
  ? false
  : T extends readonly unknown[]
    ? number extends T["length"]
      ? false
      : true
    : false;

Solution by jxhhdx #22724

  1. never is subset of any type
  2. Tuple should be readonly
  3. any[]['length'] is number
type IsTuple<T> = [T] extends [never]
  ? false
  : T extends readonly any[]
  ? number extends T["length"]
    ? false
    : true
  : false;

Solution by codeisneverodd #22333

type IsTuple<T> = [T] extends [never] ? false : T extends readonly any[] ?
// non tuple types don't have a definitive number for their length
 number extends T['length'] ? false: true : false;

Solution by Karamuto #21377

Return true when: T is not never && (T is [] || T is of any length).

Additionally, this solution supports cases such as readonly [1, 2, 3] and readonly [].

type IsTuple<T> = [T] extends [never]
  ? false
  : T extends readonly []
    ? true
    : T extends readonly [infer _Head, ...infer _Tail]
      ? true
      : false

Solution by hstevanoski #21309

// your answers
type IsTuple<T> = 
  [T] extends [never] ? false : 
  T extends [] ? true : 
  T extends readonly[infer F,...infer R] ? true : false

Solution by YqxLzx #20062

// your answers
type IsTuple<T> = [T] extends [never]
  ? false
  : T extends readonly any[]
  ? number extends T["length"]
    ? false
    : true
  : false;

Solution by fengjinlong #20060

// your answers
type IsTuple<T> = 
  [T] extends [never] ? false : 
    (T extends readonly any[]
      ? number extends T['length']
        ? false
        : true
      : false
      )

Solution by Quanzhitong #19837

type IsTuple<T> = 
  [T] extends [never] ? false : 
    T extends readonly any[]
      ? number extends T['length']
        ? false
        : true
      : false

Solution by zhaoyao91 #19701