Skip to content

Instantly share code, notes, and snippets.

@Honga1
Created November 6, 2021 18:10
Show Gist options
  • Save Honga1/7898d2c6f9322f7931c39627ed730439 to your computer and use it in GitHub Desktop.
Save Honga1/7898d2c6f9322f7931c39627ed730439 to your computer and use it in GitHub Desktop.
const tuple = ["a", "b", "c", "d"] as const;
type Tuple = typeof tuple;
type FirstElement<Tuple extends readonly any[]> = Tuple[0];
type ShiftOne<Tuple extends readonly any[]> = Tuple extends readonly [Tuple[0], ...infer U] ? U : never;
type PopOne<Tuple extends readonly any[]> = Tuple extends readonly [...infer U, Tuple[number]] ? U : never;
type LastElement<Tuple extends readonly any[]> = Tuple extends readonly [...Tuple[number], infer U] ? U : never;
type Indices<Tuple extends readonly any[], TStart extends number[]> = Tuple['length'] extends 0 ? PopOne<[0, ...TStart]> : Indices<ShiftOne<Tuple>, [Tuple['length'], ...TStart]>;
type R = ShiftOne<Tuple>;
type LE = LastElement<Tuple>;
type I = Indices<Tuple, []>
type P = PopOne<Tuple>;
@Honga1
Copy link
Author

Honga1 commented Jan 19, 2022

export type Primitive = null | string | boolean | number | undefined;
type UnpackedArray<T extends any[]> = T extends (infer U)[] ? U : never;
type KeysOfEmptyArray = keyof []

type UnpackedObject<T extends Record<string, any>> = T extends Record<string, infer Y> ? Y : never;
type IsTuple<T extends readonly any[]> = `0` extends keyof T ? true : false;

type Path<TValue, Acc extends readonly any[] = []> = TValue extends Array<any>
    ? IsTuple<TValue> extends true
        ? Path<UnpackedArray<TValue>, [...Acc, Exclude<keyof TValue, KeysOfEmptyArray>]>
        : Path<UnpackedArray<TValue>, [...Acc, number]>
    : TValue extends Record<string, any>
    ? Path<UnpackedObject<TValue>, [...Acc, keyof TValue]>
    : Acc

type TestA = [1, 2]
type TestB = [1, [2]]
type TestC = [1, {two: 2}]
type TestD = [1, {three: {three: 3, four: 4}, half: 2}]
type TestE = {a: 'cat'}

type ResultA = Path<TestA>
type ResultB = Path<TestB>
type ResultC = Path<TestC>
type ResultD = Path<TestD>
type ResultE = Path<TestE>

const testF: [1, {three: {three: 3, four: 4}, half: 2}]  = [1, {three: {three: 3, four: 4}, half: 2}];
const f: Path<typeof testF> = ['0', 'half'] // You get autocomplete here

type C = IsTuple<TestA>;
type D = IsTuple<number[]>;
type A = UnpackedArray<TestA>
type B = Path<[1, [1, number[]]]>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment