JSX
Jsx es una sintaxis XML embebida en nuestros ficheros js. Se hizo muy popular con la aparición de React. Ahora TypeScript no solo soporta y es capaz de compilar esta nueva sintaxis, si no que ademas verifica tipos.
Nuestros archivos deben de ser .tsx
var x = <any> foo; // is equivalent to: var x = foo as any;
Usando React
Para poder tener soporte sobre neustras extension jsx con react, es necesario referencias los React typings. Estos typings definen los namespaces de JSX
/// <reference path="react.d.ts" /> interface Props { name: string; } class MyComponent extends React.Component<Props, {}> { render() { return <span>{this.props.foo}</span> } } <MyComponent name="bar" />; // OK <MyComponent name={0} />; // error, `name` is not a number
Intersection types
Este concepto viene a complementar al incorporado anteriormente de Union Type.
Cuando hablamos de Union Type, estamos hablando de algo similar a esto: a | b , donde decimos que nuestra variable debe de ser del tipo a o del tipo b. Pues bien ahora el concepto de Intersection types nos dice lo contrario, nos indica que nuestra variable sera del tipo a y también del tipo b, y se escribe de la siguiente manera : a & b
function extend<T, U>(first: T, second: U): T & U { let result = <T & U> {}; for (let id in first) { result[id] = first[id]; } for (let id in second) { if (!result.hasOwnProperty(id)) { result[id] = second[id]; } } return result; } var x = extend({ a: "hello" }, { b: 42 }); var s = x.a; var n = x.b;
Un ejemplo un poco mas complejo del uso de interfaces y anidamiento mediante generics
type LinkedList<T> = T & { next: LinkedList<T> }; interface Person { name: string; } var people: LinkedList<Person>; var s = people.name; var s = people.next.name; var s = people.next.next.name; var s = people.next.next.next.name;
Y un ejemplo un poco mas claro :
interface A { a: string } interface B { b: string } interface C { c: string } var abc: A & B & C; abc.a = "hello"; abc.b = "hello"; abc.c = "hello";
Local type declarations
Similar al scope que manejan las variables declaras mediante la palabra let y const. Ahora podemos declarar de manera local a un bloque de código, una interface
function f() { if (true) { interface T { x: number } let v: T; v.x = 5; } else { interface T { x: string } let v: T; v.x = "hello"; } }
Una posibilidad que nos da esta característica, es la de poder retornar clases, sin exponer implementación. Brindando la posibilidad de crear factory’s que retornen no solo instancias si no tipos.
function getPointFactory(x: number, y: number) { class P { x = x; y = y; } return P; } var PointZero = getPointFactory(0, 0); var p1 = new PointZero(); var p2 = new PointZero(); p1.x = 2; p1.y = 9;
De igual manera podemos retornar interfaces sin exponerlas, solo exponiendo sus atributos.
function getType() { interface IManager { s: string; } var local = <IManager>{ s:"Mensaje" } return local; } var typeFirst = getType(); typeFirst.s = "Nuevo mensaje";
Los tipos locales pueden contener clases locales, interfaces locales e inclusive pueden hacer uso de generics.
function f3() { function f<X, Y>(x: X, y: Y) { class C { public x = x; public y = y; } return C; } let C = f(10, "hello"); let v = new C(); let x = v.x; // number let y = v.y; // string }