Capítulo 4. Objetos
Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com
Literales de objeto
Un conjunto de claves y valores
Cada uno con su propio tipo
Enel capítulo 3, "Uniones y literales", se desarrollaron los tipos unión y literal: cómo trabajar con primitivas como boolean
y con valores literales de las mismas como true
. Esas primitivas sólo arañan la superficie de las complejas formas de objeto que el código JavaScript utiliza habitualmente. TypeScript sería bastante inutilizable si no fuera capaz de representar esos objetos. Este capítulo tratará sobre cómo describir formas de objeto complejas y cómo TypeScript comprueba su asignabilidad.
Tipos de objetos
Cuando crea un literal de objeto con la sintaxis {...}
, TypeScript lo considerará un nuevo tipo de objeto, o forma de tipo, basándose en sus propiedades. Ese tipo de objeto tendrá los mismos nombres de propiedades y tipos primitivos que los valores del objeto. El acceso a las propiedades del valor puede hacerse con value.member
o con la sintaxis equivalente value['member']
.
TypeScript entiende que el tipo de la siguiente variable poet
es el de un objeto con dos propiedades: born
, de tipo number
, y name
, de tipo string
. Acceder a esos miembros estaría permitido, pero intentar acceder a cualquier otro nombre de miembro provocaría un error de tipo por no existir ese nombre:
const
poet
=
{
born
:
1935
,
name
:
"Mary Oliver"
,
};
poet
[
'born'
];
// Type: number
poet
.
name
;
// Type: string
poet
.
end
;
// ~~~
// Error: Property 'end' does not exist on
// type '{ born: number; name: string; }'.
Los tipos de objeto son un concepto básico para que TypeScript entienda el código JavaScript. Cada valor distinto de null
y undefined
tiene un conjunto de miembros en su forma de tipo de respaldo, por lo que TypeScript debe entender el tipo de objeto de cada valor para poder comprobarlo tipográficamente .
Declarar tipos de objetos
Inferir tipos directamente de objetos existentes está muy bien, pero con el tiempo querrás poder declarar explícitamente el tipo de un objeto. Necesitarás una forma de describir la forma de un objeto separadamente de los objetos que la satisfacen.
Los tipos de objeto pueden describirse utilizando una sintaxis similar a la de los literales de objeto, pero con tipos en lugar de valores para los campos. Es la misma sintaxis que TypeScript muestra en los mensajes de error sobre la asignabilidad de tipos.
Esta variable poetLater
es del mismo tipo que las anteriores name: string
y born: number
:
let
poetLater
:
{
born
:
number
;
name
:
string
;
};
// Ok
poetLater
=
{
born
:
1935
,
name
:
"Mary Oliver"
,
};
poetLater
=
"Sappho"
;
// Error: Type 'string' is not assignable to
// type '{ born: number; name: string; }'
Tipos de objetos alias
Escribir constantemente en tipos de objetos como { born: number; name: string; }
se volvería tedioso con bastante rapidez. Es más habitual utilizar alias de tipos para asignar un nombre a cada forma de tipo.
El fragmento de código anterior podría reescribirse con un type Poet
, que tiene la ventaja añadida de hacer que el mensaje de error de asignabilidad de TypeScript sea un poco más directo y legible:
type
Poet
=
{
born
:
number
;
name
:
string
;
};
let
poetLater
:
Poet
;
// Ok
poetLater
=
{
born
:
1935
,
name
:
"Sara Teasdale"
,
};
poetLater
=
"Emily Dickinson"
;
// Error: Type 'string' is not assignable to type 'Poet'.
Nota
La mayoría de los proyectos TypeScript prefieren utilizar la palabra clave interface
para describir los tipos de objeto, que es una característica que no trataré hasta el Capítulo 7, "Interfaces". Los tipos de objeto con alias y las interfaces soncasi idénticos: todo lo que se dice en este capítulo se aplica también a las interfaces.
Traigo a colación estos tipos de objeto ahora porque entender cómo TypeScript interpreta los literales de objeto es una parte importante del aprendizaje del sistema de tipos de TypeScript. Estos conceptos seguirán siendo importantes una vez que pasemos a las características en la siguiente sección de este libro.
Tipificación estructural
El sistema de tipos de TypeScript es de tipo estructural: es decir, cualquier valor que satisfaga un tipo puede utilizarse como valor de ese tipo. En otras palabras, cuando declaras que un parámetro o variable es de un tipo de objeto concreto, le estás diciendo a TypeScript que sea cual sea el objeto u objetos que utilices, tienen que tener esas propiedades.
Los siguientes tipos de objeto alias WithFirstName
y WithLastName
sólo declaran un único miembro de tipo string
. La variable hasBoth
resulta que tiene ambos -aunque no se haya declarado como tal explícitamente-, por lo que se puede proporcionar a variables declaradas como cualquiera de los dos tipos de objeto alias:
type
WithFirstName
=
{
firstName
:
string
;
};
type
WithLastName
=
{
lastName
:
string
;
};
const
hasBoth
=
{
firstName
:
"Lucille"
,
lastName
:
"Clifton"
,
};
// Ok: `hasBoth` contains a `firstName` property of type `string`
let
withFirstName
:
WithFirstName
=
hasBoth
;
// Ok: `hasBoth` contains a `lastName` property of type `string`
let
withLastName
:
WithLastName
=
hasBoth
;
La mecanografía estructural no es lo mismo que la mecanografía pato, que viene de la frase "Si parece un pato y grazna como un pato, probablemente sea un pato".
-
Se habla de tipado estructural cuando existe un sistema estático que comprueba el tipo -en el caso de TypeScript, el comprobador de tipos-.
-
La tipificación agachada es cuando nada comprueba los tipos de objetos hasta que se utilizan en tiempo de ejecución.
En resumen: JavaScript es de tipado duck mientras que TypeScript es de tipado estructural.
Comprobación de uso
Cuando proporciona un valor a una ubicación anotada con un tipo de objeto, TypeScript comprobará que el valor es asignable a ese tipo de objeto. Para empezar, el valor debe tener las propiedades requeridas del tipo de objeto. Si falta en el objeto algún miembro requerido en el tipo de objeto, TypeScript emitirá un error de tipo.
El siguiente tipo de objeto alias FirstAndLastNames
requiere que existan las propiedades first
y last
. Un objeto que contenga ambas se puede utilizar en una variable declarada de tipo FirstAndLastNames
, pero un objeto sin ellas no:
type
FirstAndLastNames
=
{
first
:
string
;
last
:
string
;
};
// Ok
const
hasBoth
:
FirstAndLastNames
=
{
first
:
"Sarojini"
,
last
:
"Naidu"
,
};
const
hasOnlyOne
:
FirstAndLastNames
=
{
first
:
"Sappho"
};
// Property 'last' is missing in type '{ first: string; }'
// but required in type 'FirstAndLastNames'.
Tampoco se permiten tipos no coincidentes entre ambos. Los tipos de objeto especifican tanto los nombres de las propiedades requeridas como los tipos que se espera que sean esas propiedades. Si la propiedad de un objeto no coincide, TypeScript informará de un error de tipo.
El siguiente tipo TimeRange
espera que el miembro start
sea del tipo Date
. El objeto hasStartString
está provocando un error de tipo porque su start
es del tipo string
en su lugar:
type
TimeRange
=
{
start
:
Date
;
};
const
hasStartString
:
TimeRange
=
{
start
:
"1879-02-13"
,
// Error: Type 'string' is not assignable to type 'Date'.
};
Comprobación de bienes sobrantes
TypeScript informará de un error de tipo si se declara una variable con un tipo de objeto y su valor inicial tiene más campos de los que describe su tipo. Por tanto, declarar una variable con un tipo de objeto es una forma de conseguir que el comprobador de tipos se asegure de que sólo tiene los campos esperados de ese tipo.
La siguiente variable poetMatch
tiene exactamente los campos descritos en el tipo de objeto aliasado por Poet
, mientras que extraProperty
provoca un error de tipo por tener unapropiedad extra:
type
Poet
=
{
born
:
number
;
name
:
string
;
}
// Ok: all fields match what's expected in Poet
const
poetMatch
:
Poet
=
{
born
:
1928
,
name
:
"Maya Angelou"
};
const
extraProperty
:
Poet
=
{
activity
:
"walking"
,
born
:
1935
,
name
:
"Mary Oliver"
,
};
// Error: Type '{ activity: string; born: number; name: string; }'
// is not assignable to type 'Poet'.
// Object literal may only specify known properties,
// and 'activity' does not exist in type 'Poet'.
Ten en cuenta que las comprobaciones de exceso de propiedades sólo se activan para los literales de objeto que se crean en ubicaciones declaradas como tipo de objeto. Proporcionar un literal de objeto existente evita las comprobaciones de exceso de propiedades.
Esta variable extraPropertyButOk
no provoca un error de tipo con el tipo Poet
del ejemplo anterior porque su valor inicial coincide estructuralmente con Poet
:
const
existingObject
=
{
activity
:
"walking"
,
born
:
1935
,
name
:
"Mary Oliver"
,
};
const
extraPropertyButOk
:
Poet
=
existingObject
;
// Ok
Las comprobaciones de exceso de propiedades se activarán en cualquier lugar en el que se esté creando un nuevo objeto en una ubicación que espere que coincida con un tipo de objeto -lo que, como verás en capítulos posteriores, incluye miembros de matrices, campos de clases y parámetros de funciones. Prohibir el exceso de propiedades es otra forma en la que TypeScript te ayuda a asegurarte de que tu código es limpio y hace lo que esperas. El exceso de propiedades no declaradas en sus tipos de objeto suelen ser nombres de propiedades mal escritos o código no utilizado.
Tipos de objetos anidados
Como los objetos JavaScript pueden anidarse como miembros de otros objetos, los tipos de objeto de TypeScript deben poder representar tipos de objeto anidados en el sistema de tipos. La sintaxis para hacerlo es la misma que antes, pero con un tipo de objeto { ... }
en lugar de un nombre primitivo.
Poem
se declara que el tipo es un objeto cuya propiedad author
tiene firstName: string
y lastName: string
. La variable poemMatch
es asignable a Poem
porque coincide con esa estructura, mientras que poemMismatch
no lo es porque su propiedad author
incluye name
en lugar de firstName
y lastName
:
type
Poem
=
{
author
:
{
firstName
:
string
;
lastName
:
string
;
};
name
:
string
;
};
// Ok
const
poemMatch
:
Poem
=
{
author
:
{
firstName
:
"Sylvia"
,
lastName
:
"Plath"
,
},
name
:
"Lady Lazarus"
,
};
const
poemMismatch
:
Poem
=
{
author
:
{
name
:
"Sylvia Plath"
,
},
// Error: Type '{ name: string; }' is not assignable
// to type '{ firstName: string; lastName: string; }'.
// Object literal may only specify known properties, and 'name'
// does not exist in type '{ firstName: string; lastName: string; }'.
name
:
"Tulips"
,
};
Otra forma de escribir type Poem
sería extraer la forma de la propiedad author
en su propio alias de tipo de objeto, Author
. Extraer los tipos anidados en sus propios alias de tipo también ayuda a TypeScript a dar mensajes de error de tipo más informativos. En este caso, puede decir 'Author'
en lugar de '{ firstName: string; lastName: string; }'
:
type
Author
=
{
firstName
:
string
;
lastName
:
string
;
};
type
Poem
=
{
author
:
Author
;
name
:
string
;
};
const
poemMismatch
:
Poem
=
{
author
:
{
name
:
"Sylvia Plath"
,
},
// Error: Type '{ name: string; }' is not assignable to type 'Author'.
// Object literal may only specify known properties,
// and 'name' does not exist in type 'Author'.
name
:
"Tulips"
,
};
Consejo
Por lo general, es una buena idea trasladar los tipos de objeto anidados a su propio nombre de tipo de esta forma, tanto para que el código sea más legible como para que los mensajes de error de TypeScript sean más legibles.
En capítulos posteriores verás cómo los miembros de un tipo de objeto pueden ser de otros tipos, como matrices y funciones .
Propiedades opcionales
Las propiedades de tipo de objeto no tienen por qué ser todas obligatorias en el objeto. Puedes incluir un ?
antes del :
en la anotación de tipo de una propiedad de tipo para indicar que se trata de una propiedad opcional.
Este tipo Book
sólo requiere una propiedad pages
y opcionalmente permite una author
. Los objetos que se adhieran a él pueden proporcionar author
u omitirla siempre que proporcionen pages
:
type
Book
=
{
author
?:
string
;
pages
:
number
;
};
// Ok
const
ok
:
Book
=
{
author
:
"Rita Dove"
,
pages
:
80
,
};
const
missing
:
Book
=
{
author
:
"Rita Dove"
,
};
// Error: Property 'pages' is missing in type
// '{ author: string; }' but required in type 'Book'.
Ten en cuenta que existe una diferencia entre las propiedades opcionales y las propiedades cuyo tipo incluye casualmente undefined
en una unión de tipos. Una propiedad declarada como opcional con ?
puede no existir. Una propiedad declarada como obligatoria con | undefined
debe existir, aunque su valor sea undefined
.
La propiedad editor
del siguiente tipo Writers
puede omitirse al declarar variables porque tiene un ?
en su declaración. La propiedad author
no tiene un ?
, por lo que debe existir, aunque su valor sea sólo undefined
:
type
Writers
=
{
author
:
string
|
undefined
;
editor
?:
string
;
};
// Ok: author is provided as undefined
const
hasRequired
:
Writers
=
{
author
:
undefined
,
};
const
missingRequired
:
Writers
=
{};
// ~~~~~~~~~~~~~~~
// Error: Property 'author' is missing in type
// '{}' but required in type 'Writers'.
El Capítulo7, "Interfaces", tratará más sobre otros tipos de propiedades, mientras que el Capítulo 13, "Opciones de configuración", describirá los ajustes de rigor de TypeScript en torno a propiedades opcionales.
Uniones de tipos de objeto
Es razonable que en el código TypeScript quieras ser capaz de describir un tipo que puede ser uno o más tipos de objeto diferentes que tienen propiedades ligeramente distintas. Además, es posible que tu código quiera ser capaz de estrechar el tipo entre esos tipos de objeto basándose en el valor de una propiedad.
Uniones de tipo objeto inferidas
Si a una variable se le da un valor inicial que podría ser uno de varios tipos de objeto, TypeScript deducirá que su tipo es una unión de tipos de objeto. Ese tipo de unión tendrá un constituyente para cada una de las posibles formas de objeto. Cada una de las posibles propiedades del tipo estará presente en cada uno de esos constituyentes, aunque serán ?
tipos opcionales en cualquier tipo que no tenga un valor inicial para ellas.
Este valor poem
siempre tiene una propiedad name
de tipo string
, y puede o no tener propiedades pages
y rhymes
:
const
poem
=
Math
.
random
()
>
0.5
?
{
name
:
"The Double Image"
,
pages
:
7
}
:
{
name
:
"Her Kind"
,
rhymes
:
true
};
// Type:
// {
// name: string;
// pages: number;
// rhymes?: undefined;
// }
// |
// {
// name: string;
// pages?: undefined;
// rhymes: boolean;
// }
poem
.
name
;
// string
poem
.
pages
;
// number | undefined
poem
.
rhymes
;
// boolean | undefined
Uniones explícitas de tipo objeto
Alternativamente, puedes ser más explícito sobre tus tipos de objeto siendo explícito con tu propia unión de tipos de objeto. Hacerlo requiere escribir un poco más de código, pero tiene la ventaja de darte más control sobre tus tipos de objeto. En particular, si el tipo de un valor es una unión de tipos de objeto, el sistema de tipos de TypeScript sólo permitirá acceder a las propiedades que existan en todos esos tipos de unión.
Esta versión de la variable anterior poem
está explícitamente tipada para ser un tipo de unión que siempre tiene la propiedad name
junto con pages
o rhymes
. Se permite acceder a name
porque siempre existe, pero no se garantiza que pages
y rhymes
existan:
type
PoemWithPages
=
{
name
:
string
;
pages
:
number
;
};
type
PoemWithRhymes
=
{
name
:
string
;
rhymes
:
boolean
;
};
type
Poem
=
PoemWithPages
|
PoemWithRhymes
;
const
poem
:
Poem
=
Math
.
random
()
>
0.5
?
{
name
:
"The Double Image"
,
pages
:
7
}
:
{
name
:
"Her Kind"
,
rhymes
:
true
};
poem
.
name
;
// Ok
poem
.
pages
;
// ~~~~~
// Property 'pages' does not exist on type 'Poem'.
// Property 'pages' does not exist on type 'PoemWithRhymes'.
poem
.
rhymes
;
// ~~~~~~
// Property 'rhymes' does not exist on type 'Poem'.
// Property 'rhymes' does not exist on type 'PoemWithPages'.
Restringir el acceso a miembros potencialmente inexistentes de los objetos puede ser bueno para la seguridad del código. Si un valor puede ser de varios tipos, no se garantiza que las propiedades que no existen en todos esos tipos existan en el objeto.
Del mismo modo que las uniones de tipos literales y/o primitivos deben estrecharse de tipo para acceder a propiedades que no existen en todos los constituyentes de tipo, tendrás que estrechar esas uniones de tipo objeto .
Limitación de los tipos de objetos
Si el comprobador de tipos de ve que un área de código sólo puede ejecutarse si un valor tipado en unión contiene una determinada propiedad, estrechará el tipo del valor sólo a los constituyentes que contengan esa propiedad. En otras palabras, el estrechamiento de tipos de TypeScript se aplicará a los objetos si compruebas su forma en el código.
Continuando con el ejemplo de poem
explícitamente tipado, comprueba si "pages" in poem
actúa como un protector de tipo para TypeScript para indicar que es un PoemWithPages
. Si poem
no es un PoemWithPages
, entonces debe ser un PoemWithRhymes
:
if
(
"pages"
in
poem
)
{
poem
.
pages
;
// Ok: poem is narrowed to PoemWithPages
}
else
{
poem
.
rhymes
;
// Ok: poem is narrowed to PoemWithRhymes
}
Ten en cuenta que TypeScript no permite comprobaciones de existencia de veracidad como if (poem.pages)
. Intentar acceder a una propiedad de un objeto que podría no existir se considera un error de tipo, aunque se utilice de una forma que parezca comportarse como una guarda de tipo:
if
(
poem
.
pages
)
{
/* ... */
}
// ~~~~~
// Property 'pages' does not exist on type 'Poem'.
// Property 'pages' does not exist on type 'PoemWithRhymes'.
Sindicatos discriminados
Otra forma popular de unión tipada de objetos en JavaScript y TypeScript es hacer que una propiedad del objeto indique qué forma tiene el objeto. Este tipo de unión tipada se denomina unión discriminada, y la propiedad cuyo valor indica el tipo del objeto es un discriminante. TypeScript es capaz de realizar estrechamientos de tipo para el código que guarda el tipo en propiedades discriminantes.
Por ejemplo, el tipo Poem
describe un objeto que puede ser un nuevo tipo o un nuevo tipo , y la propiedad indica cuál.PoemWithPages
o un nuevo tipo PoemWithRhymes
, y la propiedad type
indica cuál. Si poem.type
es "pages"
, entonces TypeScript es capaz de inferir que el tipo de poem
debe ser PoemWithPages
. Sin ese estrechamiento de tipos, no está garantizada la existencia de ninguna de las dos propiedades en el valor:
type
PoemWithPages
=
{
name
:
string
;
pages
:
number
;
type
:
'pages'
;
};
type
PoemWithRhymes
=
{
name
:
string
;
rhymes
:
boolean
;
type
:
'rhymes'
;
};
type
Poem
=
PoemWithPages
|
PoemWithRhymes
;
const
poem
:
Poem
=
Math
.
random
()
>
0.5
?
{
name
:
"The Double Image"
,
pages
:
7
,
type
:
"pages"
}
:
{
name
:
"Her Kind"
,
rhymes
:
true
,
type
:
"rhymes"
};
if
(
poem
.
type
===
"pages"
)
{
console
.
log
(
`It's got pages:
${
poem
.
pages
}
`
);
// Ok
}
else
{
console
.
log
(
`It rhymes:
${
poem
.
rhymes
}
`
);
}
poem
.
type
;
// Type: 'pages' | 'rhymes'
poem
.
pages
;
// ~~~~~
// Error: Property 'pages' does not exist on type 'Poem'.
// Property 'pages' does not exist on type 'PoemWithRhymes'.
Las uniones discriminadas son mi característica favorita de TypeScript, porque combinan a la perfección un elegante patrón común de JavaScript con el estrechamiento de tipos de TypeScript.El Capítulo 10, "Genéricos" y sus proyectos asociados mostrarán más sobre el uso de uniones discriminadas para datos genéricos operaciones.
Tipos de intersecciones
Los tipos de unión |
de TypeScript representan el tipo de un valor que podría ser uno de dos o más tipos diferentes. Del mismo modo que el operador de ejecución |
de JavaScript actúa como contrapartida de su operador &
, TypeScript permite representar un tipo que es varios tipos a la vez: un tipo de intersección &
. Los tipos de intersección se suelen utilizar con tipos de objetos alias para crear un nuevo tipo que combine varios tipos de objetos existentes.
Los siguientes tipos Artwork
y Writing
se utilizan para formar un tipo combinado WrittenArt
que tiene las propiedades genre
, name
y pages
:
type
Artwork
=
{
genre
:
string
;
name
:
string
;
};
type
Writing
=
{
pages
:
number
;
name
:
string
;
};
type
WrittenArt
=
Artwork
&
Writing
;
// Equivalent to:
// {
// genre: string;
// name: string;
// pages: number;
// }
Tipos de intersección puede combinarse con tipos de unión, lo que a veces resulta útil para describir uniones discriminadas en un solo tipo.
Este tipo ShortPoem
siempre tiene una propiedad author
, luego también es una unión discriminada en una propiedad type
:
type
ShortPoem
=
{
author
:
string
}
&
(
|
{
kigo
:
string
;
type
:
"haiku"
;
}
|
{
meter
:
number
;
type
:
"villanelle"
;
}
);
// Ok
const
morningGlory
:
ShortPoem
=
{
author
:
"Fukuda Chiyo-ni"
,
kigo
:
"Morning Glory"
,
type
:
"haiku"
,
};
const
oneArt
:
ShortPoem
=
{
author
:
"Elizabeth Bishop"
,
type
:
"villanelle"
,
};
// Error: Type '{ author: string; type: "villanelle"; }'
// is not assignable to type 'ShortPoem'.
// Type '{ author: string; type: "villanelle"; }' is not assignable to
// type '{ author: string; } & { meter: number; type: "villanelle"; }'.
// Property 'meter' is missing in type '{ author: string; type: "villanelle"; }'
// but required in type '{ meter: number; type: "villanelle"; }'.
Peligros de los tipos de intersección
Los tipos de intersección son un concepto útil, pero es fácil utilizarlos de forma que te confundan a ti o al compilador de TypeScript. Te recomiendo que intentes mantener el código lo más simple posible cuando los utilices.
Errores de asignación largos
Asignabilidad los mensajes de error de TypeScript se vuelven mucho más difíciles de leer cuando creas tipos de intersección complejos, como uno combinado con un tipo de unión. Éste será un tema común con el sistema de tipos de TypeScript (y con los lenguajes de programación tipados en general): cuanto más complejo sea, más difícil será entender los mensajes del comprobador de tipos.
En el caso del fragmento de código anterior ShortPoem
, sería mucho más legible dividir el tipo en una serie de tipos de objeto con alias para permitir que TypeScript imprima esos nombres:
type
ShortPoemBase
=
{
author
:
string
};
type
Haiku
=
ShortPoemBase
&
{
kigo
:
string
;
type
:
"haiku"
};
type
Villanelle
=
ShortPoemBase
&
{
meter
:
number
;
type
:
"villanelle"
};
type
ShortPoem
=
Haiku
|
Villanelle
;
const
oneArt
:
ShortPoem
=
{
author
:
"Elizabeth Bishop"
,
type
:
"villanelle"
,
};
// Type '{ author: string; type: "villanelle"; }'
// is not assignable to type 'ShortPoem'.
// Type '{ author: string; type: "villanelle"; }'
// is not assignable to type 'Villanelle'.
// Property 'meter' is missing in type
// '{ author: string; type: "villanelle"; }'
// but required in type '{ meter: number; type: "villanelle"; }'.
nunca
Los tipos de intersección también son fáciles de utilizar mal y crear con ellos un tipo imposible. Los tipos primitivos no pueden unirse como constituyentes en un tipo de intersección porque es imposible que un valor sea varios primitivos a la vez. Si se intenta unir &
dos tipos primitivos se obtendrá el tipo nunca, representado por la palabra clave never
:
type
NotPossible
=
number
&
string
;
// Type: never
La palabra clave y el tipo never
es lo que los lenguajes de programación denominan como tipo inferior, o tipo vacío. Un tipo inferior es aquel que no puede tener valores posibles y no puede ser alcanzado. No se pueden proporcionar tipos a una ubicación cuyo tipo sea un tipo inferior:
let
notNumber
:
NotPossible
=
0
;
// ~~~~~~~~~
// Error: Type 'number' is not assignable to type 'never'.
let
notString
:
never
=
""
;
// ~~~~~~~~~
// Error: Type 'string' is not assignable to type 'never'.
La mayoría de los proyectos TypeScript rara vez -o nunca- utilizan el tipo never
. Aparece de vez en cuando para representar estados imposibles en el código. La mayoría de las veces, sin embargo, es probable que se trate de un error por un mal uso de los tipos de intersección. Lo trataré más en el Capítulo 15, "Operaciones de tipos".
Resumen
En este capítulo, has ampliado tus conocimientos sobre el sistema de tipos de TypeScript para poder trabajar con objetos:
-
Cómo TypeScript interpreta los tipos a partir de literales de tipo de objeto
-
Describir los tipos literales de objeto, incluidas las propiedades anidadas y opcionales
-
Declarar, inferir y estrechar tipos con uniones de tipos literales de objetos
-
Uniones discriminadas y discriminantes
-
Combinar tipos de objeto con tipos de intersección
Consejo
Ahora que has terminado de leer este capítulo, practica lo que has aprendido en https://learningtypescript.com/objects.
¿Cómo declara un abogado su tipo TypeScript?
"¡Protesto!"
Get Aprender TypeScript now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.