Closed260

type-challengesの学習記録

YaonaYaona
YaonaYaona

回答
これでは不正解

type MyAwaited<T> = T extends Promise<infer U> ? U : never;
YaonaYaona

回答

type MyAwaited<T> = T extends PromiseLike<infer U> ? U extends PromiseLike<any> ? MyAwaited<U> : U : never;
YaonaYaona

Promiseだけなら以下でもOK

type MyAwaited<T> = T extends Promise<infer U> ? U extends Promise<any> ? MyAwaited<U> : U : never;
YaonaYaona
YaonaYaona

これだと不完全

type Includes<T extends readonly any[], U> = U extends T[number] ? true : false;
YaonaYaona

回答
完全一致は一癖ある。

type MyEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
type Includes<T extends readonly any[], U> = T extends [infer X, ...infer Y] 
  ? MyEqual<U, X> extends true
    ? true
    : Includes<Y, U>
  : false;
YaonaYaona
YaonaYaona

回答

type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer X) => any ? X : never;

なぜタプル型が返るか?
ChatGPT先生による解説:
関数の引数型は、関数のシグネチャを記述する際に、すべての引数の型を タプル型 としてまとめて表現します

YaonaYaona
YaonaYaona

回答
なんか違う。。。

type MyReadonly2<T, K = keyof T> = {
  [t in keyof T as t extends K ? never : t]: T[t]; 
} & {
  readonly [t in keyof T as t extends K ? t : never]: T[t]; 
};

YaonaYaona

回答
Kの指定方法の違い。

type MyReadonly2<T, K extends keyof T = keyof T> = {
  [t in keyof T as t extends K ? never : t]: T[t]; 
} & {
  readonly [t in keyof T as t extends K ? t : never]: T[t]; 
};

YaonaYaona
YaonaYaona

回答途中

declare function PromiseAll<A extends any[]>(values: A): A extends [arg: infer X, ...args: infer Y];
YaonaYaona

回答
これだと不完全。

declare function PromiseAll<A extends any[]>(values: A): Promise<{
  [a in keyof A]: Awaited<A[a]>;
}>;
YaonaYaona

回答

declare function PromiseAll<A extends any[]>(values: readonly [...A]): Promise<{
  [a in keyof A]: Awaited<A[a]>;
}>;
YaonaYaona
YaonaYaona

回答

type Replace<S extends string, From extends string, To extends string> = 
  From extends ''
  ? S
  : S extends `${From}${infer Y}`
    ? `${To}${Y}`
    : S extends `${infer X}${From}${infer Y}`
      ? `${X}${To}${Y}`
      : S extends `${infer X}${From}`
        ? `${X}${To}`
        : S;
YaonaYaona

回答
無駄な処理を省くと以下になる。

type Replace<S extends string, From extends string, To extends string> = 
  From extends ''
  ? S
  : S extends `${infer X}${From}${infer Y}`
    ? `${X}${To}${Y}`
    : S;
YaonaYaona
YaonaYaona

回答

type Flatten<S extends any[], T = []> = 
  T extends any[]
    ? S extends [S[0], ...args: infer X] 
      ? S[0] extends any[]
        ? Flatten<[...S[0], ...X], T>
        : Flatten<X, [...T, S[0]]>
      : T
    : never;
YaonaYaona

回答

type Flatten<S extends any[], T extends any[] = []> = 
  S extends [S[0], ...args: infer X] 
    ? S[0] extends any[]
      ? Flatten<[...S[0], ...X], T>
      : Flatten<X, [...T, S[0]]>
    : T;
YaonaYaona
YaonaYaona

回答

type KebabCase<S extends string> = 
  S extends `${infer X}${infer Y}`
    ? Y extends Uncapitalize<Y>
      ? `${Uncapitalize<X>}${KebabCase<Y>}`
      : `${Uncapitalize<X>}-${KebabCase<Y>}`
    : S;
YaonaYaona

別解

type KebabCase<S extends string> = 
  S extends `${infer X}${infer Y}`
    ? Y extends Uncapitalize<Y>
      ? `${Lowercase<X>}${KebabCase<Y>}`
      : `${Lowercase<X>}-${KebabCase<Y>}`
    : S;
YaonaYaona
YaonaYaona

回答

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

参考

そもそもの原因は、「neverは空のunionであるがdistributiveに解決しようとして、結果適用されない」ということでした。 conditional typeをdistributiveに適用しない方法が公式でも紹介されており、 [] で囲めばOKとのことなので上記のコードで解決できました。

https://www.m3tech.blog/entry/2023/03/10/142235

YaonaYaona
YaonaYaona

回答

type IsUnion<T, S = T> =
  [T] extends [never]
    ? false
    : T extends S
      ? [S] extends [T]
        ? false
        : true
      : false;
YaonaYaona
YaonaYaona

回答
配列の限界?で1000までしか不可。

type MinusOne<T extends number, C extends any[] = [1]> = 
  T extends C["length"]
    ? C extends [infer X, ...args: infer Y]
      ? [...Y]["length"]
      : C["length"]
    : MinusOne<T, [1, ...C,]>;
YaonaYaona

途中

type MinusOne<T extends number, C extends any[] = []> = 
  `${T}` extends `${infer X extends number}${infer Y extends number}`
    ? MinusOne<Y, [...C, X]>
    : C extends [...args: infer X extends number[], arg: infer Y extends number]
      ? Y extends 0
        ? MyMinusOne<Y>
        : `${Flat<X>}${MyMinusOne<Y>}` extends infer Z extends number
          ? Z
          : never
      : never;
YaonaYaona
YaonaYaona

回答
&のままではだめなので、マージする必要がある。

type PartialByKeys<T extends Object, K extends keyof T = keyof T> = {
  [t in keyof T as t extends K ? never : t]: T[t];
} & {
  [k in K]?: T[k];
} extends infer X ? {[x in keyof X]: X[x]} : never;
YaonaYaona

別解

type PartialByKeys<T extends Object, K extends keyof T = keyof T> = {
  [t in keyof Omit<T, K>]: T[t];
} & {
  [k in K]?: T[k];
} extends infer X ? {[x in keyof X]: X[x]} : never;
YaonaYaona
YaonaYaona

回答途中

type FlattenOne<S extends any[]> = 
  S extends [S[0], ...args: infer X] 
    ? S[0] extends any[]
      ? [...S[0], ...X]
      : [S[0], ...FlattenOne<[...X]>]
    : S;

type MinusOne<T extends string> =
  T extends `${infer X extends number}${infer Y extends string}`
    ? Y extends ""
      ? ["9", "0", "1", "2", "3", "4", "5", "6", "7", "8"][X]
      : Y extends "0"
        ? `${MinusOne<`${X}`>}${MinusOne<Y>}`
        : `${X}${MinusOne<Y>}`
    : never;

type FlattenDepth<T extends any[], U extends number = 1> = 
  U extends 1
  ? FlattenOne<T>
  : T extends FlattenOne<T>
      ? T
      : MinusOne<`${U}`> extends `${infer X extends number}`
        ? FlattenDepth<FlattenOne<T>, X>
        : never;

YaonaYaona

回答
だいぶ無理やり減算処理を実現。
※合っているかは不明(とりあえず今回の問題はクリアした)
※110->9になるため、MinusOneは間違っている

type FlattenOne<S extends any[]> = 
  S extends [S[0], ...args: infer X] 
    ? S[0] extends any[]
      ? [...S[0], ...FlattenOne<[...X]>]
      : [S[0], ...FlattenOne<[...X]>]
    : S;

type MinusOne<T extends string> =
  T extends `${infer X extends number}${infer Y extends string}`
    ? Y extends ""
      ? ["9", "0", "1", "2", "3", "4", "5", "6", "7", "8"][X]
      : Y extends "0"
        ? `${MinusOne<`${X}`>}${MinusOne<Y>}` extends `0${infer A}`
          ? `${A}`
          : `${MinusOne<`${X}`>}9`
        : `${X}${MinusOne<Y>}` extends `${X}9${infer Z}`
          ? `${Y}` extends `9${infer A}`
            ? `${X}9${Z}`
            : `${MinusOne<`${X}`>}9${Z}` extends `0${infer A}`
              ? `${A}`
              : `${MinusOne<`${X}`>}9${Z}`
          : `${X}${MinusOne<Y>}`
    : never;

type FlattenDepth<T extends any[], U extends number = 1> = 
  U extends 1
  ? FlattenOne<T>
  : T extends FlattenOne<T>
      ? T
      : MinusOne<`${U}`> extends `${infer X extends number}`
        ? FlattenDepth<FlattenOne<T>, X>
        : never;
YaonaYaona
YaonaYaona

回答
Union型を作成し、上の桁から比較。
不一致または桁数が異なる時に最終判定。

type Split<T extends (string | number)> = 
  `${T}` extends `${infer X extends number}${infer Y extends string}`
    ? [X, ...Split<Y>]
    : [];

type GetUnion<T extends number, U extends any[] = []> = 
  T extends U["length"]
    ? [U["length"], ...U][number]
    : GetUnion<T, [...U, U["length"]]>;

type GreaterThanAll<T extends number[], U extends number[]> =
  GetUnion<T["length"]> extends GetUnion<U["length"]>
    ? GetUnion<U["length"]> extends GetUnion<T["length"]>
      ? T extends [infer X extends number, ...infer Y extends number[]]
        ? U extends [infer A extends number, ...infer B extends number[]]
          ? GetUnion<X> extends GetUnion<A>
            ? GetUnion<A> extends GetUnion<X>
              ? GreaterThanAll<Y, B>
              : false
            : true
          : true
        : false
      : false
    : true;
    
type GreaterThan<T extends number, U extends number> = GreaterThanAll<Split<T>, Split<U>>
YaonaYaona
YaonaYaona

回答
Lの値で分岐。

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  L extends number[] = [],
> =
  T[L["length"]] extends undefined
    ? []
    : L["length"] extends Start
        ? L["length"] extends End
          ? [T[L["length"]], ...Fill<T, N, Start, End, [1, ...L]>]
          : [N, ...Fill<T, N, Start, End, [2, ...L]>]
        : L extends [infer X extends number, ...infer Y]
          ? X extends 2
            ? L["length"] extends End
              ? [T[L["length"]], ...Fill<T, N, Start, End, [1, ...L]>]
              : [N, ...Fill<T, N, Start, End, [2, ...L]>]
            : [T[L["length"]], ...Fill<T, N, Start, End, [1, ...L]>]
          : [T[L["length"]], ...Fill<T, N, Start, End, [1, ...L]>];
YaonaYaona
YaonaYaona

回答
anyの判定はkeyof

type IndexOf<T extends any[], U extends any, L extends number[] = []> =
  T extends [infer X, ...infer Y]
    ? X extends U
      ? U extends X
        ? keyof X extends keyof U
          ? keyof U extends keyof X
            ? L["length"]
            : IndexOf<Y, U, [...L, 1]>
          : IndexOf<Y, U, [...L, 1]>
        : IndexOf<Y, U, [...L, 1]>
      : IndexOf<Y, U, [...L, 1]>
    : -1;
YaonaYaona
YaonaYaona

回答
だいぶ力技パターン。

type IndexOf<T extends any[], U extends any, L extends number[] = []> =
  T extends [infer X, ...infer Y]
    ? X extends U
      ? U extends X
        ? keyof X extends keyof U
          ? keyof U extends keyof X
            ? L["length"]
            : IndexOf<Y, U, [...L, 1]>
          : IndexOf<Y, U, [...L, 1]>
        : IndexOf<Y, U, [...L, 1]>
      : IndexOf<Y, U, [...L, 1]>
    : -1;

type Reverse<T extends any[]> = T extends [...args: infer Y, arg: infer X] ? [X, ...Reverse<Y>] : [];

type Pop<T extends any[], U extends number, L extends number[] = []> =
  U extends L["length"]
    ? T
    : T extends [...infer X, infer Y]
      ? Pop<X, U, [1, ...L]>
      : [];

type LastIndexOf<T extends any[], U extends any> =
  IndexOf<Reverse<T>, U> extends infer X extends number
    ? X extends -1
      ? -1
      : Pop<Pop<T, X>, 1>["length"]
    : never;
YaonaYaona
YaonaYaona

回答
IndexOfにnever判定を追加して実施。

type IndexOf<T extends any[], U extends any, L extends number[] = []> =
  T extends [infer X, ...infer Y]
    ? [X] extends [U]
      ? [U] extends [X]
        ? keyof X extends keyof U
          ? keyof U extends keyof X
            ? L["length"]
            : IndexOf<Y, U, [...L, 1]>
          : IndexOf<Y, U, [...L, 1]>
        : IndexOf<Y, U, [...L, 1]>
      : IndexOf<Y, U, [...L, 1]>
    : -1;

type Unique<T extends any[], L extends any[] = []> = 
  T["length"] extends 0
    ? L
    : T extends [T[0], ...infer X]
      ? IndexOf<L, T[0]> extends -1
        ? [...Unique<X, [...L, T[0]]>]
        : [...Unique<X, L>]
      : [...Unique<[], [...L, T[0]]>];
YaonaYaona
YaonaYaona

回答

type NumberRange<L extends number, H extends number, T extends number[] = [], U extends number[] = []> = 
  U["length"] extends 0
    ? T["length"] extends L
      ? NumberRange<L, H, [1, ...T], [...U, L]>
      : NumberRange<L, H, [1, ...T], U>
    : T["length"] extends H
      ? [...U, T["length"]][number]
      : NumberRange<L, H, [1, ...T], [...U, T["length"]]>;
YaonaYaona
YaonaYaona

回答

type Find<T extends string, U extends string> = 
  T extends `${infer X}${infer Y}`
    ? X extends U
      ? true
      : Find<Y, U>
    : false;
type Count<T extends string, U extends any[] = []> = T extends `${infer X}${infer Y}` ? Count<Y, [...U, 1]> : U['length'];
type FirstUniqueCharIndex<T extends string, U extends string = ''> =
  T extends `${infer X}${infer Y}`
    ? Find<Y, X> extends true
      ? FirstUniqueCharIndex<Y, `${U}${X}`>
      : Find<U, X> extends true
        ? FirstUniqueCharIndex<Y, `${U}${X}`>
        : Count<U>
    : -1;
YaonaYaona
YaonaYaona

回答

type Find<T extends any[], U extends any> =
  T extends [infer X, ...infer Y]
    ? U extends X
      ? X extends U
        ? true
        : Find<Y, U>
      : Find<Y, U>
    : false;
type FindEles<T extends any[], U extends any[] = [], S extends any[] = []> = 
  T extends [infer X, ...infer Y]
    ? Find<[...Y, ...U, ...S], X> extends true
      ? FindEles<Y, U, [...S, X]>
      : FindEles<Y, [...U, X], S>
    : U;
YaonaYaona
YaonaYaona

回答

type Flatten<S extends any[], T extends any[] = []> = 
  S extends [S[0], ...args: infer X] 
    ? S[0] extends any[]
      ? Flatten<[...S[0], ...X], T>
      : Flatten<X, [...T, S[0]]>
    : T;
type Count<T extends any[], U extends any, S extends any[] = []> = 
  T extends [infer X, ...infer Y]
    ? X extends U
      ? Count<Y, U, [...S, 1]>
      : Count<Y, U, S>
    : S['length'];
type CountElementNumberToObject<T extends any[]> = 
  Flatten<T> extends infer X extends any[]
    ? {
      [x in X[number]]: Count<X, x>;
    }
    : never;
YaonaYaona
YaonaYaona
type Count<T extends string, U extends any[] = []> = T extends `${infer X}${infer Y}` ? Count<Y, [...U, 1]> : U['length'];
type FindAll<T extends string, P extends string, S extends any[] = [], R extends string = ''> = 
  P extends ''
    ? S
    : T extends `${infer X extends string}${P}${infer Y}`
      ? `${P}${Y}` extends `${infer A}${infer B}`
        ? FindAll<B, P, [...S, Count<`${R}${X}`>], `${R}${X}${A}`>
        : S
      : S;
YaonaYaona
YaonaYaona

回答

type Init<T extends any[] = [], U extends number = 0> =
  T['length'] extends U
    ? T
    : Init<[...T, []], U>;
type TransposeCore<T extends any[][], U extends any[], L extends any[] = []> =
  U[L['length']] extends undefined
    ? []
    : T[L['length']] extends undefined
      ? [[U[L['length']]], ...TransposeCore<T, U, [...L, 1]>]
      : [[...T[L['length']], U[L['length']]], ...TransposeCore<T, U, [...L, 1]>]
type Transpose<M extends number[][], L extends any[][] = []> = 
  M['length'] extends 0
    ? L
    : M extends [infer X extends any[], ...infer Y extends any[][]]
      ? L extends []
        ? Init<L, X['length']> extends infer Z extends any[][]
          ? Transpose<Y, TransposeCore<Z, X> extends infer A extends any[][] ? A : never>
          : never
        : Transpose<Y, TransposeCore<L, X> extends infer A extends any[][] ? A : never>
      : L;
YaonaYaona
YaonaYaona

途中

type JSONSchema2TS<T extends {type?: any, enum?: any, properties?: any, items?: any, required?: string[]}> = 
  T['enum'] extends any[]
    ? T['enum'][number]
    : T['type'] extends 'string'
      ? string
      : T['type'] extends 'number'
        ? number
        : T['type'] extends 'boolean'
          ? boolean
          : T['type'] extends 'object'
            ? T['properties'] extends object
              ? {
                [t in keyof T['properties']]?: JSONSchema2TS<T['properties'][t]>;
              }
              : Record<string, unknown>
            : T['type'] extends 'array'
              ? T['items'] extends object
                ? JSONSchema2TS<T['items']>[]
                : unknown[]
              : never;
YaonaYaona

回答
Omitだけ参考。

type JSONSchema2TS<T extends {type?: any, enum?: any, properties?: any, items?: any, required?: string[]}> = 
  T['enum'] extends any[]
    ? T['enum'][number]
    : T['type'] extends 'string'
      ? string
      : T['type'] extends 'number'
        ? number
        : T['type'] extends 'boolean'
          ? boolean
          : T['type'] extends 'object'
            ? T['properties'] extends object
              ? T['required'] extends string[]
                ? Omit<{
                      [t in T['required'][number]]: JSONSchema2TS<T['properties'][t]>
                    } & {
                      [t in keyof T['properties']]?: JSONSchema2TS<T['properties'][t]>
                    }, never>
                : {
                  [t in keyof T['properties']]?: JSONSchema2TS<T['properties'][t]>;
                }
              : Record<string, unknown>
            : T['type'] extends 'array'
              ? T['items'] extends object
                ? JSONSchema2TS<T['items']>[]
                : unknown[]
              : never;
YaonaYaona
YaonaYaona

回答
配列限界のため、100以上のケースは無理。
が、これ以上は沼なのでやらない。

type LengthArray<T extends number, L extends number[] = []> =
  L['length'] extends T
    ? L
    : LengthArray<T, [...L, 1]>;
type SquareCore<T extends number[], U extends number, L extends number[] = [], S extends number[] = []> =
  U extends L['length']
    ? S['length']
    : SquareCore<T, U, [...L, 1], [...T, ...S]>;
type Square<N extends number> = 
  `${N}` extends `-${infer X extends number}`
    ? LengthArray<X> extends infer Y extends number[]
      ? SquareCore<Y, X>
      : never
    : LengthArray<N> extends infer X extends number[]
      ? SquareCore<X, N>
      : never;
YaonaYaona
YaonaYaona

回答
先ほどの処理を流用。

type LengthArray<T extends number, L extends number[] = []> =
  L['length'] extends T
    ? L
    : LengthArray<T, [...L, 1]>;
type TriangularCore<T extends number[], U extends number, L extends number[] = []> =
  U extends L['length']
    ? T['length']
    : TriangularCore<[...T, ...L], U, [...L, 1]>;
type Triangular<N extends number> = TriangularCore<LengthArray<N>, N>;
YaonaYaona
YaonaYaona

回答

type MergeAll<XS extends any[], S extends object = {}> = 
  XS extends [infer X extends object, ...infer Y extends object[]]
    ? {
      [x in keyof X]: X[x];
    } extends infer Z
      ? MergeAll<Y, {
        [x in keyof Z | keyof S]:
          x extends keyof S
            ? x extends keyof Z
              ? S[x] | Z[x]
              : S[x]
            : x extends keyof Z
              ? Z[x]
              : never;
      }>
      : never
    : S
YaonaYaona
YaonaYaona

回答

type MyEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
type Find<T extends any[], U extends any> =
  T extends [infer X, ...infer Y]
    ? MyEqual<X, U> extends true
      ? true
      : Find<Y, U>
    : false;
type CheckRepeatedTuple<T extends unknown[]> = 
  T extends [infer X, ...infer Y]
    ? Find<Y, X> extends true
      ? true
      : CheckRepeatedTuple<Y>
    : false;
YaonaYaona
YaonaYaona

回答

type Length<T extends number, S extends any[] = []> = 
  T extends S['length']
    ? S
    : Length<T, [1, ...S]>;
type Hanoi<N extends number, From = 'A', To = 'B', Intermediate = 'C'> = HanoiCore<N, From, To, Intermediate>
type HanoiCore<T extends number, From = 'A', To = 'B', Intermediate = 'C', S extends number[] = []> =
  T extends 0
    ? []
    : [
        ...HanoiCore<Length<T> extends [infer X, ...infer Y] ? Y['length'] : never, From, Intermediate, To>,
        [From, To],
        ...HanoiCore<Length<T> extends [infer X, ...infer Y] ? Y['length'] : never, Intermediate, To, From>
      ];
YaonaYaona
YaonaYaona

途中回答

type Sum<T extends number, S extends number> = [...GetArray<T>, ...GetArray<S>]['length'];
type GetArray<T extends number, L extends any[] = []> =
  T extends L['length']
  ? L
  : GetArray<T, [...L, 1]>;
type GetTail<T extends any[]> =
  T extends [...infer X, infer Y]
  ? Y
  : T[0];
type PascalCoreLoop<T extends any[], L extends any[] = []> = 
  T extends undefined
    ? 1
    : T['length'] extends L['length']
      ? []
      : [PascalCore<T, L['length']>, ...PascalCoreLoop<T, [1, ...L]>];
type PascalCore<T extends any[], L extends number> =
  T extends undefined
  ? 1
  : Sum<T[L], T[Sum<L, 1> extends infer X extends number ? X : T['length']] extends infer X extends number ? X : 0>
type Pascal<N extends number, L extends any[] = []> =
  N extends L['length']
  ? L
  : Pascal<N, [...L, PascalCoreLoop<GetTail<L>>]>
YaonaYaona

回答

type Sum<T extends number, S extends number> = [...GetArray<T>, ...GetArray<S>]['length'];
type GetArray<T extends number, L extends any[] = []> =
  T extends L['length']
  ? L
  : GetArray<T, [...L, 1]>;
type GetTail<T extends any[]> =
  T extends [...infer X, infer Y]
  ? Y
  : T[0];
type PascalCoreLoop<T extends any[], L extends any[] = []> =
  T extends undefined
  ? []
  : L['length'] extends Sum<T['length'], 0>
  ? []
  : [PascalCore<T, L['length']>, ...PascalCoreLoop<T, [1, ...L]>];
type PascalCore<T extends any[], L extends number> =
  T extends undefined
  ? 1
  : Sum<T[L], T[Sum<L, 1> extends infer X extends number ? X : T['length']] extends infer X extends number ? X : 0>;

type Pascal<N extends number, L extends any[] = []> =
  N extends L['length']
  ? L
  : Pascal<N, [...L, [1, ...PascalCoreLoop<GetTail<L>>]]>;
YaonaYaona
YaonaYaona

途中回答
'ABC' | 'DEF'の場合に不可。

type IsBoolean<T extends string> =
  [T] extends [`${true}`]
    ? true
    : [T] extends [`${false}`]
      ? true
      : false;
type IsNever<T extends string> =
  [T] extends [never]
    ? true
    : false;
type IsPrimitive<T extends string> =
  `${string}` extends T
    ? true
    : `${number}` extends T
      ? true
      : `${bigint}` extends T
        ? true
        : `${boolean}` extends T
          ? true
          : false;


type IsFixedStringLiteralType<S extends string> = 
  IsNever<S> extends true
    ? false
    : [S]extends [`${infer X}${boolean}${infer Y}`]
      ? [`${X}${boolean}${Y}`] extends [S]
        ? false
        : true
      : S extends `${infer X}${infer Y}`
          ? IsFixedStringLiteralTypeCore<X> extends false
            ? false
            : IsFixedStringLiteralType<Y>
          : IsFixedStringLiteralTypeCore<S>;
          
type IsFixedStringLiteralTypeCore<S extends string> = 
   true extends IsNever<S>
    ? false
    : true extends IsBoolean<S>
      ? true
      : true extends IsPrimitive<S>
        ? false
        : true;
YaonaYaona

回答
他者回答を参考

type MyEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
type IsFixedStringLiteralType<S extends string> =
  {} extends Record<S, 1>
    ? false
    : MyEqual<[S], S extends S ? [S] : never>;
YaonaYaona
YaonaYaona

回答

type Reverse<T extends string, S extends string = ""> = 
  T extends ""
    ? S
    : T extends `${infer X}${infer Y}`
      ? Reverse<Y, `${X}${S}`>
      : never;

type LongestCommonPrefixCore<T extends string, S extends string, L extends string = ""> = 
  T extends ""
    ? ""
    : S extends ""
      ? ""
      : S extends `${infer _}${T}`
        ? Reverse<T>
        : LongestCommonPrefixCore<T extends `${infer X}${infer Y}` ? `${Y}` : never, S>;

type LongestCommonPrefix<T extends string[], P extends string = ''> = 
  T extends [infer X extends string, infer Y extends string, infer Z extends string]
    ? LongestCommonPrefixCore<Reverse<X>, Reverse<Y>> extends infer A extends string
      ? A extends ""
        ? ""
        : LongestCommonPrefixCore<Reverse<A>, Reverse<Z>>
      : ""
    : never;
YaonaYaona
YaonaYaona

回答

const alphabets = [...[...Array(26)].map((a, b) => (10 + b).toString(36)), ...[...Array(26)].map((a, b) => (10 + b).toString(36)).join('').toUpperCase()];
type Alphabets = [
  "a",
  "b",
  "c",
  "d",
  "e",
  "f",
  "g",
  "h",
  "i",
  "j",
  "k",
  "l",
  "m",
  "n",
  "o",
  "p",
  "q",
  "r",
  "s",
  "t",
  "u",
  "v",
  "w",
  "x",
  "y",
  "z",
  "A",
  "B",
  "C",
  "D",
  "E",
  "F",
  "G",
  "H",
  "I",
  "J",
  "K",
  "L",
  "M",
  "N",
  "O",
  "P",
  "Q",
  "R",
  "S",
  "T",
  "U",
  "V",
  "W",
  "X",
  "Y",
  "Z"
][number]

type ArrayUnionType<T extends string[]> = T[number];
type IsAlphabet<S extends string> = S extends Alphabets ? true : false;
このスクラップは2024/12/28にクローズされました