HotScript: La alegría de la gimnasia tipográfica TypeScript

  1. Ayer, aprendí sobre una biblioteca (hotscript) que es muy cómoda para la programación de tipo ts. La mayoría de los tipos de gimnasia no se usan con frecuencia, pero cuando es necesario, se requiere cierto tipo de base de gimnasia.
  2. Primero echemos un vistazo a cómo usarlo y cómo llamarlo cómodo.
  3. enlace de secuencia de comandos

223854503-b54f6a62-9f21-4953-aaa3-5d54699516a7.png

Es fácil de entender, pero el ejemplo no es genial? , Ven a

1684233474080.jpg

Hotscript proporciona la mayoría de los tipos de funciones que se necesitan en la vida diaria, y la operación de conversión de tipos ahora es útil.

  1. Estoy seguro de que el contenido del artículo no será tan simple. A continuación, exploremos cómo se implementa el hotscript, y también lo implementé brevemente. Enlace de experiencia en línea

  2. En primer lugar, consideremos las dificultades, luego cómo controlar los parámetros, realizar conversiones y cómo guardar tipos.

    1. Si el tipo está guardado, use la interfaz para darse cuenta, entonces, ¿por qué usar la interfaz para mirar el código?

1684233982026.jpgEs posible obtener los valores de otros atributos en la interfaz, entonces esto es fácil de hacer y los datos se pueden fusionar en la interfaz cuando se ejecute la función correspondiente en el futuro.


interface Fn {
  [rawArgs]: unknown;
  arg: this[rawArgs] extends Array<unknown> ? this[rawArgs] : unknown[];
  arg0: this[rawArgs] extends [infer arg, ...any] ? arg : never;
  arg1: this[rawArgs] extends [any, infer arg, ...any] ? arg : never;
  running: unknown;
}
type foo = Print<Fn & { [rawArgs]: [1, 2, 3, 4] }>;

type f1  = foo["arg"]//[1, 2, 3, 4]
type f2  = foo["arg0"]//1
type f3  = foo["arg1"]//2

De esta manera, podemos guardar los parámetros requeridos en la interfaz y luego implementar un complemento y luego convertirlo en una cadena y podemos operar en tal combinación.

namespace Number {
   export type Add<
      A extends number | slot = slot,
      B extends number | slot = slot
    > = PartialApply<AddFn, [A, B]>;

  interface AddFn extends Fn {
    running: this["arg"] extends [
      infer A extends number,
      infer B extends number
    ]
      ? UtilAdd<A, B>
      : never;
  }
  
 //在来一个简单的toString来实现接下里的组合使用
 namespace String {
  export type toString = PartialApply<toStringFn, []>;
  interface toStringFn extends Fn {
    running: `${this["arg0"]}`;
  }
}

Esta es nuestra lógica de implementación específica. En la actualidad, PartialApply y UtilAdd no se han introducido aquí. UtilAdd es la implementación de suma más pura y simple.

type Build<
  T extends number,
  Result extends Array<never> = [],
> = Result["length"] extends T ? Result : Build<T, [...Result, never]>;

export type Add<A extends number, B extends number> = [
  ...Build<A>,
  ...Build<B>
]["length"];

type test = Add<1,2> // 3;

El punto es PartialApply, pero lo siguiente puede hacer que su cuero cabelludo hormiguee, pero primero podemos ver lo que hace MergeArgs en PartialApply, y luego ver la implementación de PartialApply en su conjunto. los parámetros en PartialApply se pueden usar Number.Addpara un slottipo. La razón principal aquí es que los parámetros de tipo deben reorganizarse y los parámetros predeterminados se pueden combinar con el significado de una ranura de posición de parámetro.

WeChatc82e1ef1ddf638d105de876afc418523.png

¿De qué sirve esto, porque se puede usar de una manera similar al curry y, al mismo tiempo, puede evitar que la profundidad del tipo sea demasiado profunda cuando se pasa el tipo genérico al usar un cierre similar para implementar el tipo? recursivamente A continuación, veamos esta implementación de Type, por supuesto, esto es un poco más conciso, no en el código fuente de hotscript.

type MergeArgs<
  pipedArgs extends any[],
  partialArgs extends any[],
  Result extends unknown[] = []
> = partialArgs extends [infer partialFirst, ...infer lastPartialFirst]
  ? partialFirst extends slot
    ? pipedArgs extends [infer pipedArgsFirst, ...infer lastPipedArgsFirst]
      ? MergeArgs<
          lastPipedArgsFirst,
          lastPartialFirst,
          [...Result, pipedArgsFirst]
        >
      : [...Result, ...lastPartialFirst]
    : MergeArgs<pipedArgs, lastPartialFirst, [...Result, partialFirst]>
  : [...Result, ...pipedArgs];

interface PartialApply<T extends Fn, partialArgs extends unknown[]> extends Fn {
  running: Running<T, MergeArgs<this["arg"], partialArgs>>;
}

Ahora puedes implementar un tipo que llame a esta función

type Running<G extends Fn, P> = (G & {
    //在这里我们对参数进行合并传入
  [rawArgs]: P extends Array<any> ? P : [P];
})["running"];

export type Pipe<T, G extends Fn[]> = G extends [
  infer A extends Fn,
  ...infer B extends Fn[]
]
  ? Pipe<Running<A, T>, B>
  : T;

Entonces lo usamos

imagen.png

Tal vez la introducción no sea fácil de entender, pero esto en sí es para la conveniencia de la operación de tipos, permitiendo a los usuarios operar tipos declarativamente, sin prestar especial atención a los puntos clave.Finalmente, adjunto una demostración de mi implementación, la api específica y hotScript Hay una pequeña discrepancia.

imagen.png

Supongo que te gusta

Origin juejin.im/post/7233695223402381369
Recomendado
Clasificación