Open4

TSの型をこねこねする

uzmoiuzmoi

swapに型を付ける

const temp = object[key1];
object[key1] = object[key2];
object[key2] = temp;

だめなの

// asserts-isでは型を拡張できない
declare const swap: <T, K extends keyof T>(object: T, key1: K, key2: K) =>
    asserts object is T & { [_ in K]: T[K] };

const obj = { hoge: "", fuga: 0 };
swap(obj, "hoge", "fuga");
// ここでも`obj.hoge`の型がstringのまま(string | numberであるべき)

よさげなの
Intersection

type Swapable<T, K extends keyof T> =
    {
        [_ in K]: Intersection<
            K extends unknown ? { x: T[K] } : never
        > extends { x: infer U } ? U : never;
    };
declare const swap: <T, K extends keyof T>(object: T & Swapable<T, K>, key1: K, key2: K) => void;
uzmoiuzmoi

Repeat

type Range09 = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type Times<T, U extends Range09> = {
    0: [];
    1: [T];
    2: [T, T];
    3: [T, T, T];
    4: [T, T, T, T];
    5: [T, T, T, T, T];
    6: [T, T, T, T, T, T];
    7: [T, T, T, T, T, T, T];
    8: [T, T, T, T, T, T, T, T];
    9: [T, T, T, T, T, T, T, T, T];
};

type Repeat10<T extends readonly unknown[]> = [
    ...T, ...T, ...T, ...T, ...T,
    ...T, ...T, ...T, ...T, ...T,
];

type RepeatInternal<T, U extends string, V extends readonly T[]> = (
    U extends `${infer X extends Range09}${infer Rest}`
        ? {
            x: [...Repeat10<V>, ...Times<T, X>]
        } extends { x: infer __ extends readonly T[] }
            ? Rest extends "" ? __ : RepeatInternal<T, Rest, __>
            : never
        : never
);
type Repeat<T, U extends number> = (
    number extends U
        ? readonly T[]
        : RepeatInternal<T, `${U}`, readonly []>
);

type RepeatR<T, U extends number> = (
    number extends U ? readonly T[]
    : U extends Range09 ? Times<T, U>
    : `${U}` extends `${infer Rest extends number}${Range09}`
        ? [
            ...Repeat10<RepeatR<T, Rest>>,
            ...Times<T, `${U}` extends `${Rest}${infer X extends Range09}` ? X : never>,
        ]
        : never
);
uzmoiuzmoi

一番シンプルなの

type Repeat<T, U extends number, V extends unknown[] = []> =
    V["length"] extends U ? V : Repeat<T, U, [...V, T]>;
uzmoiuzmoi

non-nullableな型{}で書くと意味が分かりづらいからNonNullable<unknown>とか書くといいかも。