¿Qué significa Record<K, T> en Typescript?
Typescript 2.1 introdujo el tipo Record , describiéndolo en un ejemplo:
// For every properties K of type T, transform it to U function mapObject<K extends string, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>
Y la página Tipos avanzados menciona Record bajo el encabezado Tipos asignados junto con Readonly , Partial y Pick , en lo que parece ser su definición:
type Record<K extends string, T> = { [P in K]: T; }
Readonly, Partial y Pick son homomórficos mientras que Record no lo es. Una pista de que Record no es homomórfico es que no necesita un tipo de entrada para copiar propiedades desde:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
Y eso es. Además de las citas anteriores, no hay otra mención de Record en typescriptlang.org .
¿Alguien puede dar una definición simple de lo que es Record ?
¿ Record<K,T> es simplemente una forma de decir "todas las propiedades de este objeto tendrán el tipo T "? Probablemente no todas las propiedades, ya que K tiene algún propósito...
¿El genérico K prohíbe claves adicionales en el objeto que no sean K , o las permite y simplemente indica que sus propiedades no se transforman en T ?
Con el ejemplo dado:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>¿Es exactamente igual a este?:
type ThreeStringProps = {prop1: string, prop2: string, prop3: string}
- ¿Alguien puede dar una definición simple de lo que es
Record?
Un Record<K, T> es un tipo de objeto cuyas claves de propiedad son K y cuyos valores de propiedad son T Es decir, keyof Record<K, T> es equivalente a K y Record<K, T>[K] es (básicamente) equivalente a T
- ¿
Record<K,T>es simplemente una forma de decir "todas las propiedades de este objeto tendrán el tipoT"? Probablemente no todos los objetos, ya queKtiene algún propósito...
Como observa, K tiene un propósito... limitar las claves de propiedad a valores particulares. Si desea aceptar todas las claves posibles con valores de cadena, podría hacer algo como Record<string, T> , pero la forma idiomática de hacerlo es usar una firma de índice como { [k: string]: T } .
- ¿El genérico
Kprohíbe claves adicionales en el objeto que no seanK, o las permite y simplemente indica que sus propiedades no se transforman enT?
No "prohíbe" exactamente claves adicionales: después de todo, generalmente se permite que un valor tenga propiedades que no se mencionan explícitamente en su tipo... pero no reconocería que tales propiedades existen:
declare const x: Record<"a", string>; xb; // error, Property 'b' does not exist on type 'Record<"a", string>'y los trataría como propiedades en exceso que a veces son rechazadas:
declare function acceptR(x: Record<"a", string>): void; acceptR({a: "hey", b: "you"}); // error, Object literal may only specify known propertiesy a veces aceptado:
const y = {a: "hey", b: "you"}; acceptR(y); // okay
Con el ejemplo dado:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>¿Es exactamente igual a este?:
type ThreeStringProps = {prop1: string, prop2: string, prop3: string}
¡Sí!
Espero que ayude. ¡Buena suerte!
Un Registro le permite crear un nuevo tipo a partir de una Unión. Los valores de la unión se utilizan como atributos del nuevo tipo.
Por ejemplo, digamos que tengo una Unión como esta:
type CatNames = "miffy" | "boris" | "mordred"; Ahora quiero crear un objeto que contenga información sobre todos los gatos, puedo crear un nuevo tipo usando los valores en la unión CatNames como claves.
type CatList = Record<CatNames, {age: number}> Si quiero satisfacer esta CatList , debo crear un objeto como este:
const cats: CatList = { miffy: { age:99 }, boris: { age:16 }, mordred: { age:600 } }Obtienes una seguridad de tipo muy fuerte:
CatNames , obtengo un error. Esto es especialmente útil porque es probable que CatNames se importe de otro archivo y se use en muchos lugares. Usé esto recientemente para crear un componente de Status . El componente recibiría una propiedad de status y luego representaría un icono. He simplificado bastante el código aquí con fines ilustrativos.
Tuve una unión como esta:
type Statuses = "failed" | "complete";Usé esto para crear un objeto como este:
const icons: Record< Statuses, { iconType: IconTypes; iconColor: IconColors } > = { failed: { iconType: "warning", iconColor: "red" }, complete: { iconType: "check", iconColor: "green" };Luego podría renderizar desestructurando un elemento del objeto en accesorios, así:
const Status = ({status}) => <Icon {...icons[status]} /> Si la unión de Statuses se amplía o cambia más adelante, sé que mi componente de estado no se compilará y obtendré un error que puedo corregir de inmediato. Esto me permite agregar estados de error adicionales a la aplicación.
Tenga en cuenta que la aplicación real tenía docenas de estados de error a los que se hacía referencia en varios lugares, por lo que este tipo de seguridad fue extremadamente útil.