¿Puede describir qué es el lenguaje TypeScript?
Qué puede hacer que JavaScript o las bibliotecas disponibles no pueden hacer, que me daría razones para considerarlo?
Escribí esta respuesta originalmente cuando Typescript aún estaba caliente de la imprenta. Cinco años después, esta es una buena visión general, pero mira la respuesta de Lodewijk]11 más abajo para profundizar
Para hacerse una idea de lo que quiero decir, vea el vídeo introductorio de Microsoft sobre el lenguaje.
Para un gran proyecto de JavaScript, la adopción de TypeScript podría resultar en un software más robusto, mientras que todavía se puede desplegar donde se ejecutaría una aplicación normal de JavaScript.
Es de código abierto, pero sólo se obtiene el inteligente Intellisense mientras se escribe si se utiliza un IDE compatible. Inicialmente, esto era sólo Visual Studio de Microsoft (también señalado en la entrada del blog de Miguel de Icaza). Hoy en día, otros IDEs también ofrecen soporte para TypeScript.
Como ejemplo, aquí hay algo de TypeScript (puedes jugar con esto en el TypeScript Playground)
class Greeter {
greeting: string;
constructor (message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
Y aquí está el JavaScript que produciría
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
Observe cómo el TypeScript define el tipo de las variables miembro y los parámetros de los métodos de la clase. Esto se elimina al traducir a JavaScript, pero el IDE y el compilador lo utilizan para detectar errores, como pasar un tipo numérico al constructor.
También es capaz de inferir tipos que no están explícitamente declarados, por ejemplo, determinaría que el método greet()
devuelve una cadena.
TypeScript es un superconjunto tipado de JavaScript que se compila a JavaScript - typescriptlang.org. JavaScript es un lenguaje de programación desarrollado por el Comité Técnico 39 de la EMCA, que es un grupo de personas compuesto por muchas partes interesadas. El TC39 es un comité auspiciado por ECMA: una organización interna de estándares. JavaScript tiene muchas implementaciones diferentes por parte de muchos proveedores distintos (por ejemplo, Google, Microsoft, Oracle, etc.). El objetivo de JavaScript es ser la lengua franca de la web. TypeScript es un superconjunto del lenguaje JavaScript que tiene un único compilador de código abierto y está desarrollado principalmente por un único proveedor: Microsoft. El objetivo de TypeScript es ayudar a detectar los errores con antelación mediante un sistema de tipos y hacer que el desarrollo de JavaScript sea más eficiente. Esencialmente, TypeScript logra sus objetivos de tres maneras:
- **El lenguaje JavaScript (no el tiempo de ejecución) está estandarizado a través de los estándares ECMAScript. No todos los navegadores y tiempos de ejecución de JavaScript soportan todas las características de todos los estándares de ECMAScript (ver este resumen). TypeScript permite el uso de muchas de las últimas características de ECMAScript y las traduce a los objetivos de ECMAScript más antiguos que elijas (ver la lista de objetivos de compilación bajo la opción de compilador
--target
). Esto significa que puedes utilizar con seguridad las nuevas características, como los módulos, las funciones lambda, las clases, el operador de propagación y la desestructuración, sin dejar de ser compatible con navegadores y tiempos de ejecución de JavaScript más antiguos.- Sistema de tipos avanzado - El soporte de tipos no es parte del estándar ECMAScript y probablemente nunca lo será debido a la naturaleza interpretada en lugar de compilada de JavaScript. El sistema de tipos de TypeScript es increíblemente rico e incluye: interfaces, enums, tipos híbridos, genéricos, tipos de unión/intersección, modificadores de acceso y mucho más. El sitio web oficial de TypeScript ofrece una visión general de estas características. El sistema de tipos de Typescript está a la altura de la mayoría de los otros lenguajes tipados y en algunos casos podría decirse que es más potente.
- Soporte de herramientas para desarrolladores - El compilador de TypeScript puede ejecutarse como un proceso en segundo plano para soportar tanto la compilación incremental como la integración con el IDE, de forma que puedas navegar, identificar problemas, inspeccionar posibilidades y refactorizar tu código base más fácilmente.
Relación de TypeScript con otros lenguajes de JavaScript
TypeScript tiene una filosofía única en comparación con otros lenguajes que compilan a JavaScript. El código JavaScript es código TypeScript válido; TypeScript es un superconjunto de JavaScript. Casi puedes cambiar el nombre de tus archivos
.js
a archivos.ts
y empezar a usar TypeScript (ver "interoperabilidad de JavaScript" más abajo). Los archivos TypeScript se compilan a JavaScript legible, de modo que la migración de vuelta es posible y la comprensión del TypeScript compilado no es difícil en absoluto. TypeScript se basa en los éxitos de JavaScript al tiempo que mejora sus puntos débiles. Por un lado, tienes herramientas a prueba de futuro que toman los estándares modernos de ECMAScript y los compilan a versiones antiguas de JavaScript, siendo Babel la más popular. Por otro lado, tenemos lenguajes que pueden diferir totalmente de JavaScript y que tienen como objetivo JavaScript, como CoffeeScript, Clojure, Dart, Elm, Haxe, Scala.js, y un montón más (ver esta lista). Estos lenguajes, aunque podrían ser mejores que el futuro de JavaScript, corren un mayor riesgo de no encontrar suficiente adopción para que su futuro esté garantizado. También es posible que tenga más problemas para encontrar desarrolladores experimentados para algunos de estos lenguajes, aunque los que encuentre a menudo pueden ser más entusiastas. La interoperabilidad con JavaScript también puede ser un poco más complicada, ya que están más alejados de lo que realmente es JavaScript. TypeScript se encuentra entre estos dos extremos, equilibrando así el riesgo. TypeScript no es una opción arriesgada bajo ningún concepto. Requiere muy poco esfuerzo para acostumbrarse si estás familiarizado con JavaScript, ya que no es un lenguaje completamente diferente, tiene un excelente soporte de interoperabilidad de JavaScript y ha visto mucha adopción recientemente.Tipificación estática opcional e inferencia de tipos
JavaScript está tipado dinámicamente. Esto significa que JavaScript no sabe de qué tipo es una variable hasta que se instancie en tiempo de ejecución. Esto también significa que puede ser demasiado tarde. TypeScript añade soporte de tipos a JavaScript. Los errores causados por falsas suposiciones de que alguna variable es de un tipo determinado pueden ser completamente erradicados si juegas bien tus cartas (lo estricto que escribas tu código o si lo escribes depende de ti). TypeScript hace que la tipificación sea un poco más fácil y mucho menos explícita mediante el uso de la inferencia de tipos. Por ejemplo:
var x = "hola"
en TypeScript es lo mismo quevar x : cadena = "hola"
. El tipo se infiere simplemente de su uso. Incluso si no tecleas explícitamente los tipos, siguen estando ahí para salvarte de hacer algo que de otro modo daría lugar a un error en tiempo de ejecución. TypeScript es opcionalmente tipado por defecto. Por ejemplo,función dividePorDos(x) { devuelve x / 2 }
es una función válida en TypeScript que puede ser llamada con cualquier tipo de parámetro, aunque llamarla con una cadena obviamente resultará en un error de tiempo de ejecución. Tal y como estás acostumbrado en JavaScript. Esto funciona, porque cuando no se asignó explícitamente un tipo y no se pudo inferir el tipo, como en el ejemplo de divideByTwo, TypeScript asignará implícitamente el tipoany
. Esto significa que la firma de tipo de la función divideByTwo se convierte automáticamente enfunción divideByTwo(x : any) : any
. Hay una bandera del compilador para no permitir este comportamiento:--noImplicitAny
. Activar esta bandera le da un mayor grado de seguridad, pero también significa que tendrá que escribir más. Los tipos tienen un coste asociado. En primer lugar, hay una curva de aprendizaje, y en segundo lugar, por supuesto, le costará un poco más de tiempo configurar una base de código utilizando una tipificación estricta adecuada también. En mi experiencia, estos costes merecen totalmente la pena en cualquier base de código seria que compartas con otros. Un estudio a gran escala de los lenguajes de programación y la calidad del código en Github sugiere que "los lenguajes tipados estáticamente, en general, son menos propensos a los defectos que los tipos dinámicos, y que la tipificación fuerte es mejor que la débil en el mismo sentido ". Es interesante observar que este mismo documento encuentra que TypeScript es menos propenso a los errores que JavaScript: Para aquellos con coeficientes positivos podemos esperar que el lenguaje está asociado con, ceteris paribus, un mayor número de correcciones de defectos. Estos lenguajes incluyen C, C++, JavaScript, Objective-C, Php, y Python. Los lenguajes Clojure, Haskell, Ruby, Scala, y TypeScript, tienen coeficientes negativos, lo que implica que estos lenguajes tienen menos que la media para dar lugar a confirmaciones de corrección de defectos.Soporte IDE mejorado
La experiencia de desarrollo con TypeScript es una gran mejora sobre JavaScript. El IDE es informado en tiempo real por el compilador de TypeScript sobre su rica información de tipos. Esto da un par de ventajas importantes. Por ejemplo, con TypeScript, puedes hacer con seguridad refactorizaciones como renombrar todo tu código base. A través de la finalización de código, puedes obtener ayuda en línea sobre cualquier función que una biblioteca pueda ofrecer. Ya no es necesario recordarlas o buscarlas en referencias en línea. Los errores de compilación se informan directamente en el IDE con una línea roja garabateada mientras estás ocupado codificando. En definitiva, esto permite un aumento significativo de la productividad en comparación con el trabajo con JavaScript. Uno puede pasar más tiempo codificando y menos tiempo depurando. Hay una amplia gama de IDEs que tienen un excelente soporte para TypeScript, como Visual Studio Code, WebStorm, Atom y Sublime.
Comprobación estricta de nulos
Los errores en tiempo de ejecución de la forma
no se puede leer la propiedad 'x' de undefined
oundefined no es una función
son muy comúnmente causados por errores en el código JavaScript. De entrada, TypeScript ya reduce la probabilidad de que se produzcan este tipo de errores, ya que no se puede utilizar una variable que no sea conocida por el compilador de TypeScript (con la excepción de las propiedades de las variables de tipo "cualquiera"). Sin embargo, todavía es posible utilizar por error una variable que esté definida comoundefined
. Sin embargo, con la versión 2.0 de TypeScript puedes eliminar este tipo de errores mediante el uso de tipos no anulables. Esto funciona como sigue: Con la comprobación estricta de nulos activada (bandera del compilador--strictNullChecks
) el compilador de TypeScript no permitirá que se asigneundefined
a una variable a menos que se declare explícitamente que es de tipo anulable. Por ejemplo,let x : number = undefined
dará lugar a un error de compilación. Esto encaja perfectamente con la teoría de tipos ya queundefined
no es un número. Uno puede definirx
para que sea un tipo de suma denúmero
yindefinido
para corregir esto:let x : número | indefinido = indefinido
. Una vez que se sabe que un tipo es anulable, es decir, que es de un tipo que también puede tener el valornull
oundefined
, el compilador de TypeScript puede determinar, mediante un análisis de tipos basado en el flujo de control, si tu código puede utilizar una variable con seguridad o no. En otras palabras, cuando compruebas que una variable esundefined
a través de, por ejemplo, una sentenciaif
, el compilador de TypeScript deducirá que el tipo en esa rama del flujo de control de tu código ya no es nullable y, por lo tanto, puede utilizarse con seguridad. He aquí un ejemplo sencillo:
let x: number | undefined;
if (x !== undefined) x += 1; // this line will compile, because x is checked.
x += 1; // this line will fail compilation, because x might be undefined.
Durante la construcción, el codiseñador de la conferencia de 2016 de TypeScript, Anders Hejlsberg, dio una explicación detallada y una demostración de esta característica: video (de 44:30 a 56:30).
Para utilizar TypeScript se necesita un proceso de compilación de código JavaScript. El proceso de compilación suele tardar sólo un par de segundos, dependiendo, por supuesto, del tamaño de tu proyecto. El compilador de TypeScript soporta la compilación incremental (bandera del compilador --watch
) para que todos los cambios posteriores puedan ser compilados a mayor velocidad.
El compilador de TypeScript puede alinear la información del mapa fuente en los archivos .js generados o crear archivos .map separados. La información del mapa de fuentes puede ser utilizada por utilidades de depuración como Chrome DevTools y otros IDE para relacionar las líneas del JavaScript con las que las generaron en el TypeScript. Esto permite establecer puntos de interrupción e inspeccionar variables durante el tiempo de ejecución directamente en el código TypeScript. La información del mapa de fuentes funciona bastante bien, ya existía mucho antes de TypeScript, pero la depuración de TypeScript no suele ser tan buena como cuando se usa JavaScript directamente. Por ejemplo, la palabra clave this
. Debido al cambio en la semántica de la palabra clave this
en torno a los cierres desde ES2015, this
puede existir realmente durante el tiempo de ejecución como una variable llamada _this
(ver esta respuesta). Esto puede confundirte durante la depuración, pero generalmente no es un problema si lo sabes o inspeccionas el código JavaScript. Hay que tener en cuenta que Babel sufre exactamente el mismo tipo de problema.
Hay algunos otros trucos que el compilador de TypeScript puede hacer, como generar código de intercepción basado en decoradores, generar código de carga de módulos para diferentes sistemas de módulos y analizar JSX. Sin embargo, es probable que necesites una herramienta de compilación además del compilador de Typescript. Por ejemplo, si quieres comprimir tu código tendrás que añadir otras herramientas a tu proceso de compilación para hacerlo.
Hay plugins de compilación de TypeScript disponibles para Webpack, Gulp, Grunt y prácticamente cualquier otra herramienta de compilación de JavaScript que exista. La documentación de TypeScript tiene una sección sobre integración con herramientas de compilación que las cubre todas. También está disponible un linter en caso de que quieras comprobar aún más el tiempo de compilación. También hay un gran número de proyectos semilla que te ayudarán a empezar con TypeScript en combinación con un montón de otras tecnologías como Angular 2, React, Ember, SystemJS, Webpack, Gulp, etc.
Dado que TypeScript está tan estrechamente relacionado con JavaScript, tiene grandes capacidades de interoperabilidad, pero se requiere algo de trabajo extra para trabajar con bibliotecas de JavaScript en TypeScript. Las definiciones de TypeScript son necesarias para que el compilador de TypeScript entienda que las llamadas a funciones como _.groupBy
o angular.copy
o $.fadeOut
no son en realidad declaraciones ilegales. Las definiciones de estas funciones se colocan en archivos .d.ts
.
La forma más sencilla que puede adoptar una definición es permitir que un identificador se utilice de cualquier manera. Por ejemplo, cuando se utiliza Lodash, un archivo de definición de una sola línea declare var _ : any
le permitirá llamar a cualquier función que desee sobre _
, pero entonces, por supuesto, también puede cometer errores: _.foobar()
sería una llamada legal de TypeScript, pero es, por supuesto, una llamada ilegal en tiempo de ejecución. Si quieres un soporte de tipos adecuado y completar el código, tu archivo de definición debe ser más exacto (ver lodash definitions para un ejemplo).
Los módulos Npm que vienen pre-empaquetados con sus propias definiciones de tipo son automáticamente entendidos por el compilador de TypeScript (ver documentación). Para casi cualquier otra biblioteca JavaScript semipopular que no incluya sus propias definiciones, alguien ya ha puesto a disposición las definiciones de tipos a través de otro módulo npm. Estos módulos llevan el prefijo "@types/" y provienen de un repositorio de Github llamado DefinitelyTyped.
Hay una advertencia: las definiciones de tipos deben coincidir con la versión de la biblioteca que estás utilizando en tiempo de ejecución. Si no lo hacen, TypeScript podría no permitirte llamar a una función o desreferenciar una variable que existe o permitirte llamar a una función o desreferenciar una variable que no existe, simplemente porque los tipos no coinciden con el tiempo de ejecución en tiempo de compilación. Así que asegúrese de cargar la versión correcta de las definiciones de tipos para la versión correcta de la biblioteca que está utilizando.
Para ser honesto, hay una pequeña molestia en esto y puede ser una de las razones por las que no elijas TypeScript, sino que vayas por algo como Babel que no sufre de tener que obtener definiciones de tipos en absoluto. Por otro lado, si sabes lo que estás haciendo puedes superar fácilmente cualquier tipo de problema causado por archivos de definición incorrectos o ausentes.
Cualquier archivo .js
puede ser renombrado a un archivo .ts
y ejecutado a través del compilador de TypeScript para obtener sintácticamente el mismo código JavaScript como salida (si era sintácticamente correcto en primer lugar). Incluso cuando el compilador de TypeScript obtiene errores de compilación, seguirá produciendo un archivo .js
. Incluso puede aceptar archivos .js
como entrada con la bandera --allowJs
. Esto te permite empezar con TypeScript de inmediato. Desafortunadamente, es probable que se produzcan errores de compilación al principio. Hay que recordar que no se trata de errores de tipo "show-stopping" como los que se producen con otros compiladores.
Los errores de compilación que se obtienen al principio cuando se convierte un proyecto JavaScript a un proyecto TypeScript son inevitables por la naturaleza de TypeScript. TypeScript comprueba la validez de todo el código y, por tanto, necesita conocer todas las funciones y variables que se utilizan. Por lo tanto, las definiciones de tipo tienen que estar en su lugar para todos ellos, de lo contrario se producirán errores de compilación. Como se mencionó en el capítulo anterior, para casi cualquier marco de trabajo de JavaScript hay archivos .d.ts
que pueden adquirirse fácilmente con la instalación de paquetes DefinitelyTyped. Sin embargo, puede ser que hayas utilizado alguna librería oscura para la que no hay definiciones de TypeScript disponibles o que hayas polifuncionalizado algunas primitivas de JavaScript. En ese caso, debes proporcionar definiciones de tipo para estos bits para que desaparezcan los errores de compilación. Simplemente cree un archivo .d.ts
e inclúyalo en el array files
de tsconfig.json, para que siempre sea considerado por el compilador de TypeScript. En él declara los bits que TypeScript no conoce como de tipo any
. Una vez que hayas eliminado todos los errores puedes ir introduciendo gradualmente el tipado en esas partes según tus necesidades.
También será necesario trabajar en la (re)configuración de tu pipeline de compilación para introducir TypeScript en el pipeline de compilación. Como se mencionó en el capítulo sobre la compilación, hay un montón de buenos recursos por ahí y te animo a buscar proyectos de semillas que utilizan la combinación de herramientas con las que quieres trabajar.
El mayor obstáculo es la curva de aprendizaje. Te animo a que juegues con un pequeño proyecto al principio. Mira cómo funciona, cómo se construye, qué archivos utiliza, cómo se configura, cómo funciona en tu IDE, cómo se estructura, qué herramientas utiliza, etc. Convertir una gran base de código JavaScript a TypeScript es factible cuando se sabe lo que se está haciendo. Lee este blog como ejemplo sobre convertir 600k líneas a TypeScript en 72 horas). Sólo asegúrate de que tienes un buen conocimiento del lenguaje antes de dar el salto.
TypeScript es de código abierto (con licencia Apache 2, ver GitHub) y está respaldado por Microsoft. Anders Hejlsberg, el principal arquitecto de C#, está liderando el proyecto. Es un proyecto muy activo; el equipo de TypeScript ha estado publicando un montón de nuevas características en los últimos años y todavía están previstas un montón de grandes características (ver la hoja de ruta). Algunos datos sobre la adopción y la popularidad:
"TypeScript Fundamentals" -- un video-curso de Pluralsight por Dan Wahlin y John Papa es una muy buena, actualmente (25 de marzo de 2016) actualizada para reflejar TypeScript 1.8, introducción a Typescript.
Para mí las características realmente buenas, además de las buenas posibilidades de intellisense, son las clases, interfaces, módulos, la facilidad de implementar AMD, y la posibilidad de usar el depurador de Visual Studio Typescript cuando se invoca con IE.
En resumen: Si se utiliza como se pretende, Typescript puede hacer que la programación de JavaScript sea más fiable, y más fácil. Puede aumentar la productividad del programador de JavaScript de forma significativa a lo largo de todo el SDLC.