¿Qué Record<K, T>
significa en mecanografiado?
Typecript 2.1 introdujo el Record
tipo, 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>
ver Typecript 2.1
Y el Tipos avanzada página menciona Record
bajo los tipos mapeados en dirección al lado 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 se necesita un tipo de entrada para copiar propiedades de:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
Y eso es. Además de las citas anteriores, no hay otra mención Record
en typescriptlang.org .
Preguntas
¿Alguien puede dar una definición simple de lo que
Record
es?¿Es
Record<K,T>
simplemente una forma de decir "todas las propiedades en este objeto tendrán tipoT
"? Probablemente no todas las propiedades, ya queK
tiene algún propósito ...¿El
K
genérico prohíbe claves adicionales en el objeto que no lo sonK
, o las permite y solo indica que sus propiedades no se transformanT
?Con el ejemplo dado:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
¿Es exactamente lo mismo que esto ?:
type ThreeStringProps = {prop1: string, prop2: string, prop3: string}
fuente
Respuestas:
A
Record<K, T>
es un tipo de objeto cuyas claves de propiedad sonK
y cuyos valores de propiedad sonT
. Es decir,keyof Record<K, T>
es equivalente aK
, yRecord<K, T>[K]
es (básicamente) equivalente aT
.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, puede hacer algo comoRecord<string, T>
, pero la forma idiomática de hacerlo es utilizar una firma de índice como{ [k: string]: T }
.No "prohíbe" exactamente claves adicionales: después de todo, generalmente se permite que un valor tenga propiedades no mencionadas explícitamente en su tipo ... pero no reconocería que tales propiedades existen:
y los trataría como propiedades en exceso que a veces se rechazan:
y a veces aceptado:
¡Si!
Espero que ayude. ¡Buena suerte!
fuente
Record<string, V>
para decir{[x: string]: V}
si quieres; Probablemente incluso he hecho esto yo mismo. La versión de firma de índice es más directa: son del mismo tipo, pero la primera es un alias de tipo de un tipo mapeado que se evalúa como una firma de índice, mientras que la segunda es solo la firma de índice directamente. En igualdad de condiciones, recomendaría lo último. Del mismo modo, no lo usaríaRecord<"a", string>
en lugar de a{a: string}
menos que hubiera alguna otra razón contextual convincente para hacerlo.Record<string, V>
solo tiene sentido si ya sabes cómo funcionan las firmas de índice en TypeScript. Por ejemplo, dadox: Record<string, string>
,x.foo
aparentemente será unstring
momento de compilación, pero en realidad es probable que lo seastring | undefined
. Esta es una brecha en cómo--strictNullChecks
funciona (ver # 13778 ). Yo prefiero que se ocupan de los recién llegados{[x: string]: V}
directamente en lugar de esperar que siga la cadena deRecord<string, V>
a través{[P in string]: V}
de la conducta índice de la firma.Un registro le permite crear un nuevo tipo a partir de una unión. Los valores en la Unión se utilizan como atributos del nuevo tipo.
Por ejemplo, digamos que tengo una Unión como esta:
Ahora quiero crear un objeto que contenga información sobre todos los gatos, puedo crear un nuevo tipo usando los valores de CatName Union como claves.
Si quiero satisfacer esta CatList, debo crear un objeto como este:
Obtienes seguridad de tipo muy fuerte:
Ejemplo de reacción en el mundo real.
Utilicé esto recientemente para crear un componente de estado. El componente recibiría un accesorio de estado y luego representaría un icono. He simplificado mucho el código aquí con fines ilustrativos
Tuve una unión como esta:
Usé esto para crear un objeto como este:
Entonces podría renderizar mediante la desestructuración de un elemento del objeto en accesorios, así:
Si la unión de estados se extiende o cambia más tarde, sé que mi componente de estado no se compilará y recibiré un error que puedo solucionar 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 hizo referencia en varios lugares, por lo que este tipo de seguridad fue extremadamente útil.
fuente
type Statuses
vive en tipings NO definidos por usted? De lo contrario, puedo ver algo así como una interfaz con una enumeración que se ajusta mejor, ¿verdad?Dictionary<enum, additional_metadata>
. El tipo de registro es una excelente manera de representar ese patrón de enumeración + metadatos.