TypeScript

TypeScript

Tutorial TypeScript: Interfaces y su implementación

TypeScript interfaces: definición y uso. Domina la definición y uso de interfaces en TypeScript con ejemplos prácticos y detallados.

Aprende TypeScript y certifícate

Definición y sintaxis de interfaces

Después de explorar las bases de las clases en TypeScript, es momento de introducir las interfaces. Las interfaces son una herramienta poderosa que nos permite definir la forma que deben tener los objetos, actuando como contratos que garantizan que ciertas estructuras de datos cumplan con un conjunto específico de propiedades y métodos.

En esta lección, aprenderemos a definir interfaces y cómo nuestras clases pueden implementarlas para asegurar que cumplen con el contrato definido por la interfaz.

¿Qué es una interfaz?

Una interfaz en TypeScript es como un plano o un contrato. Define qué propiedades y métodos (y sus tipos) debe tener un objeto para ser considerado compatible con esa interfaz. A diferencia de las clases, las interfaces no tienen implementación (no tienen lógica dentro de los métodos, solo la firma) y no existen en el código JavaScript final después de la compilación; son una característica puramente de TypeScript para la verificación de tipos en tiempo de desarrollo.

Se declaran utilizando la palabra clave interface.

// Definición básica de una interfaz para representar una persona
interface Person {
  // Propiedades requeridas (obligatorias)
  id: number;
  name: string;

  // Propiedad opcional (puede estar presente o no)
  age?: number; // El signo ? indica que esta propiedad es opcional

  // Propiedad de solo lectura (solo se puede asignar en la inicialización)
  readonly passportNumber: string;

  // Métodos que un objeto que cumpla esta interfaz debe tener (solo la firma)
  greet(message: string): void; // Un método llamado greet que recibe un string y no devuelve nada
  getDetails(): string;       // Un método llamado getDetails que devuelve un string
}
  • Propiedades: Defines el nombre y tipo de las propiedades. Pueden ser obligatorias (por defecto), opcionales (?), o de solo lectura (readonly). La palabra clave readonly en una interfaz significa que un objeto que cumpla esa interfaz no debería poder modificar esa propiedad una vez que se le asigna un valor (generalmente en el momento de su creación).
  • Métodos: Defines solo la firma del método: su nombre, los tipos de sus parámetros y su tipo de retorno. No se incluye el cuerpo del método (la lógica).

Las interfaces son increíblemente flexibles y pueden describir la forma de casi cualquier objeto.

Implementando interfaces en clases

El propósito principal de definir interfaces es crear contratos que nuestras clases puedan prometer cumplir. Cuando una clase implementa una interfaz, TypeScript verifica que esa clase proporcione todos los miembros requeridos (propiedades y métodos obligatorios) definidos en la interfaz, con los tipos correctos.

Para hacer que una clase implemente una interfaz, usamos la palabra clave implements seguida del nombre de la interfaz. Una clase puede implementar una o varias interfaces (separadas por comas).

Sintaxis básica

La sintaxis para implementar una interfaz es la siguiente:

// Definimos una interfaz para un servicio de almacenamiento
interface StorageService {
  // Método para guardar datos
  save(key: string, value: string): void;

  // Método para cargar datos
  load(key: string): string | null; // Puede devolver un string o null
}

// Creamos una clase que implementa StorageService
// Esta clase DEBE tener los métodos save y load con las firmas exactas
class LocalStorageService implements StorageService {
  // Las propiedades requeridas por la interfaz irían aquí si las hubiera (ej: un 'name')
  // name: string = "local-storage"; // Ejemplo si la interfaz tuviera 'name: string;'

  // Implementación del método save de la interfaz
  save(key: string, value: string): void {
    localStorage.setItem(key, value); // Lógica real del método
    console.log(`Datos guardados para la clave: ${key}`);
  }

  // Implementación del método load de la interfaz
  load(key: string): string | null {
    const data = localStorage.getItem(key); // Lógica real del método
    console.log(`Datos cargados para la clave: ${key}`);
    return data; // Devuelve string o null, según la firma de la interfaz
  }

  // Podemos añadir métodos adicionales que NO estén en la interfaz
  clearAll(): void {
    localStorage.clear();
    console.log("Limpiado todo el almacenamiento local.");
  }
}

// Creamos una instancia de la clase que implementa la interfaz
const myStorage = new LocalStorageService();

myStorage.save("username", "alice"); // Usar un método implementado
const user = myStorage.load("username"); // Usar otro método implementado
if (user) {
  console.log(`Usuario cargado: ${user}`);
}

myStorage.clearAll(); // Usar un método adicional de la clase

TypeScript verificará en tiempo de compilación si LocalStorageService realmente tiene save y load con las firmas correctas. Si falta alguno o la firma no coincide (por ejemplo, save devuelve number), TypeScript mostrará un error.

Implementando Propiedades Opcionales y Readonly

Cuando una interfaz tiene propiedades opcionales (?) o de solo lectura (readonly), la clase que la implementa debe cumplir con esos requisitos:

  • Propiedades Opcionales: La clase puede definir la propiedad opcional, pero no está obligada a hacerlo.
  • Propiedades readonly: La clase debe definir la propiedad readonly y asegurarse de que solo se le asigne un valor (generalmente en el constructor).
interface Configuration {
  // Propiedad obligatoria
  apiUrl: string;
  // Propiedad opcional
  timeout?: number;
  // Propiedad de solo lectura
  readonly version: string;
}

class ApiService implements Configuration {
  apiUrl: string; // Implementa propiedad obligatoria
  timeout?: number; // Implementa propiedad opcional (podríamos omitirla)
  readonly version: string; // Implementa propiedad readonly

  constructor(url: string, apiVersion: string, requestTimeout?: number) {
    this.apiUrl = url;
    this.version = apiVersion; // Asignamos el valor a la propiedad readonly aquí
    this.timeout = requestTimeout; // Asignamos valor a la opcional si existe
  }

  // Método para ilustrar uso (no requerido por la interfaz)
  fetchData(): void {
    console.log(`Workspaceing from ${this.apiUrl} (v${this.version}) with timeout ${this.timeout || 'default'}`);
    // No podríamos hacer: this.version = "new-version"; // Error porque version es readonly
  }
}

const service = new ApiService("https://api.example.com", "1.0", 5000);
service.fetchData();

const simpleService = new ApiService("https://api.another.com", "2.0"); // Omitimos el timeout opcional
simpleService.fetchData();

Implementando múltiples interfaces

Una clase puede implementar múltiples interfaces simultáneamente, lo que permite componer comportamientos de diferentes contratos:

// Interfaz para algo que se puede guardar
interface Saveable {
  save(): boolean; // Devuelve true si se guardó correctamente
}

// Interfaz para algo que se puede cargar
interface Loadable {
  load(id: string): boolean; // Carga por ID, devuelve true si se encontró
}

// Nuestra clase que implementa ambas interfaces
class UserProfileManager implements Saveable, Loadable {
  userId: string | null = null;
  userData: any = null; // Usamos 'any' temporalmente, idealmente sería un tipo más específico

  constructor(initialUserId?: string) {
      if (initialUserId) {
          this.load(initialUserId); // Intentar cargar al iniciar
      }
  }

  // Implementación del método save de Saveable
  save(): boolean {
    if (this.userId && this.userData) {
      console.log(`Guardando datos para usuario ${this.userId}...`);
      // Aquí iría la lógica real para guardar (ej: a un archivo, API)
      return true; // Simulación de guardado exitoso
    }
    console.log("No hay datos o ID de usuario para guardar.");
    return false;
  }

  // Implementación del método load de Loadable
  load(id: string): boolean {
    console.log(`Cargando datos para usuario ${id}...`);
    // Aquí iría la lógica real para cargar (ej: desde un archivo, API)
    // Simulación: encontrar datos si el ID es "user123"
    if (id === "user123") {
      this.userId = id;
      this.userData = { name: "Charlie", age: 40 }; // Datos cargados
      console.log("Usuario cargado exitosamente.");
      return true; // Simulación de carga exitosa
    }
    console.log("Usuario no encontrado.");
    this.userId = null;
    this.userData = null;
    return false; // Simulación de carga fallida
  }
}

// Creamos una instancia del Manager
const manager = new UserProfileManager();

manager.load("user123"); // Llama al método load
manager.save();          // Llama al método save

manager.load("user456"); // Llama al método load (fallará)
manager.save();          // Llama al método save (fallará)

Implementación con propiedades privadas

Las interfaces solo definen la estructura pública de una clase. Podemos implementar una interfaz y añadir propiedades o métodos privados adicionales:

interface ICounter {
  count: number;
  increment(): void;
  decrement(): void;
  reset(): void;
}

class Counter implements ICounter {
  count: number;
  private initialValue: number;
  
  constructor(initialValue: number = 0) {
    this.count = initialValue;
    this.initialValue = initialValue;
  }
  
  increment(): void {
    this.count++;
  }
  
  decrement(): void {
    this.count--;
  }
  
  reset(): void {
    this.count = this.initialValue;
  }
  
  // Método privado adicional que no está en la interfaz
  private logCount(): void {
    console.log(`Current count: ${this.count}`);
  }
}

Implementación con accesores

Podemos implementar propiedades de interfaz utilizando getters y setters en la clase:

interface IPerson {
  firstName: string;
  lastName: string;
  fullName: string;
}

class Person implements IPerson {
  private _firstName: string;
  private _lastName: string;
  
  constructor(firstName: string, lastName: string) {
    this._firstName = firstName;
    this._lastName = lastName;
  }
  
  get firstName(): string {
    return this._firstName;
  }
  
  set firstName(value: string) {
    this._firstName = value;
  }
  
  get lastName(): string {
    return this._lastName;
  }
  
  set lastName(value: string) {
    this._lastName = value;
  }
  
  get fullName(): string {
    return `${this._firstName} ${this._lastName}`;
  }
}

const person = new Person("John", "Doe");
console.log(person.fullName); // Output: John Doe
person.firstName = "Jane";
console.log(person.fullName); // Output: Jane Doe

Caso práctico: implementación de interfaces para componentes

Las interfaces son especialmente útiles cuando desarrollamos componentes reutilizables:

interface IComponent {
  render(): string;
  update(props: any): void;
}

class Button implements IComponent {
  private label: string;
  private onClick: () => void;
  
  constructor(label: string, onClick: () => void) {
    this.label = label;
    this.onClick = onClick;
  }
  
  render(): string {
    return `<button class="btn" onclick="handleClick()">${this.label}</button>`;
  }
  
  update(props: { label?: string; onClick?: () => void }): void {
    if (props.label) {
      this.label = props.label;
    }
    if (props.onClick) {
      this.onClick = props.onClick;
    }
  }
  
  // Método específico de Button que no está en la interfaz
  handleClick(): void {
    this.onClick();
  }
}

class Image implements IComponent {
  private src: string;
  private alt: string;
  
  constructor(src: string, alt: string) {
    this.src = src;
    this.alt = alt;
  }
  
  render(): string {
    return `<img src="${this.src}" alt="${this.alt}" />`;
  }
  
  update(props: { src?: string; alt?: string }): void {
    if (props.src) {
      this.src = props.src;
    }
    if (props.alt) {
      this.alt = props.alt;
    }
  }
}

La implementación de interfaces en clases es una práctica fundamental en TypeScript que promueve el diseño orientado a contratos y facilita la creación de código más modular, mantenible y fácil de probar.

Extensión de interfaces

Las interfaces en TypeScript no solo pueden ser implementadas por clases, sino que también pueden extenderse entre sí para crear estructuras más complejas y reutilizables. La extensión de interfaces nos permite construir interfaces más específicas a partir de otras más generales, siguiendo el principio de composición que es fundamental en el diseño de software.

Sintaxis básica de extensión

Para extender una interfaz, utilizamos la palabra clave extends:

interface Animal {
  name: string;
  age: number;
}

interface Pet extends Animal {
  owner: string;
  vaccinated: boolean;
}

En este ejemplo, la interfaz Pet hereda todas las propiedades de Animal (name y age) y añade sus propias propiedades (owner y vaccinated). Cualquier objeto que implemente Pet deberá proporcionar valores para las cuatro propiedades.

const myDog: Pet = {
  name: "Rex",
  age: 3,
  owner: "Alice",
  vaccinated: true
};

Extendiendo múltiples interfaces

Una interfaz puede extender de múltiples interfaces a la vez, combinando todos sus miembros.

// Interfaz para identificar algo
interface Identifiable {
  id: string;
}

// Interfaz para algo que tiene una fecha de creación
interface Timestamped {
  createdAt: Date;
}

// Interfaz para un Usuario (hereda de Identifiable y Timestamped)
// Un User DEBE tener id (de Identifiable) y createdAt (de Timestamped)
interface UserProfileInterface extends Identifiable, Timestamped {
  name: string; // Además, un UserProfile tiene un nombre
}

// Una clase que implemente UserProfileInterface debe tener id, createdAt y name
class BasicUser implements UserProfileInterface {
  id: string; // De Identifiable
  createdAt: Date; // De Timestamped
  name: string; // De UserProfileInterface

  constructor(id: string, name: string) {
    this.id = id;
    this.name = name;
    this.createdAt = new Date(); // Inicializamos el miembro heredado
  }
}

const basicUser = new BasicUser("user-007", "James Bond");
console.log(`${basicUser.name} (ID: ${basicUser.id}) created at ${basicUser.createdAt.toDateString()}`);

Esta técnica es especialmente útil para crear interfaces modulares que pueden combinarse según las necesidades específicas de cada caso.

Redefinición de propiedades

Al extender interfaces, podemos redefinir propiedades para hacerlas más específicas, siempre que el nuevo tipo sea compatible con el original:

interface Shape {
  color: string;
  area(): number;
}

interface Circle extends Shape {
  radius: number;
  // Redefinimos el método area con una firma más específica
  area(): number;
}

class CircleImpl implements Circle {
  color: string;
  radius: number;
  
  constructor(color: string, radius: number) {
    this.color = color;
    this.radius = radius;
  }
  
  area(): number {
    return Math.PI * this.radius * this.radius;
  }
}

Extensión y sobrescritura de propiedades opcionales

Podemos convertir propiedades opcionales en obligatorias al extender interfaces:

interface Config {
  endpoint: string;
  timeout?: number;
  retries?: number;
}

interface StrictConfig extends Config {
  // Convertimos propiedades opcionales en obligatorias
  timeout: number;
  retries: number;
  // Añadimos nuevas propiedades
  logLevel: 'debug' | 'info' | 'warn' | 'error';
}

const devConfig: Config = {
  endpoint: "https://api.dev.example.com"
  // timeout y retries son opcionales
};

const prodConfig: StrictConfig = {
  endpoint: "https://api.example.com",
  timeout: 5000,      // Ahora es obligatorio
  retries: 3,         // Ahora es obligatorio
  logLevel: "error"
};

Interfaces anidadas y extensión

Las interfaces pueden contener definiciones de otras interfaces, y estas también pueden extenderse:

interface Address {
  street: string;
  city: string;
  zipCode: string;
  country: string;
}

interface Person {
  name: string;
  address: Address;
}

interface Employee extends Person {
  employeeId: string;
  department: string;
  // Podemos extender la definición anidada
  address: Address & {
    officeNumber?: string;
  };
}

const employee: Employee = {
  name: "John Smith",
  employeeId: "E12345",
  department: "Engineering",
  address: {
    street: "123 Main St",
    city: "San Francisco",
    zipCode: "94105",
    country: "USA",
    officeNumber: "4B"
  }
};

Interfaces vs. tipos: cuándo usar cada uno

Ya conoces los alias de tipo (type) para dar nombres a tipos, y ahora las interfaces (interface) para definir la forma de los objetos y clases. A menudo, pueden parecer muy similares, especialmente para definir la estructura de un objeto:

Sintaxis básica

La sintaxis para definir ambos constructos es ligeramente diferente:

// Usando Type Alias para la forma de un punto
type PointType = {
  x: number;
  y: number;
};

// Usando Interface para la forma de un punto
interface PointInterface {
  x: number;
  y: number;
}

// Ambos funcionan para tipar variables y objetos literales
const point1: PointType = { x: 10, y: 20 };
const point2: PointInterface = { x: 30, y: 40 };

// Y son estructuralmente compatibles (puedes asignar uno al otro si tienen la misma forma)
const point3: PointType = point2; // OK
const point4: PointInterface = point1; // OK

Sin embargo, hay diferencias clave en lo que pueden describir y cómo se comportan en cuanto a extensibilidad y uso con clases:

  • Lo que pueden describir:
    • interface: Principalmente describe la forma de objetos. Puede tener propiedades y firmas de métodos.
    • type: Puede dar nombre a cualquier tipo, incluyendo primitivos (type UserId = string;), uniones (type Status = "active" | "inactive";), tuplas (type Coordinates = [number, number];), firmas de funciones (type Comparator = (a, b) => number;), y la forma de objetos.
  • Extensibilidad y Clases:
    • interface: Puede ser extendida por otras interfaces (interface Pet extends Animal {}) y implementada por clases (class Dog implements Pet {}). Están diseñadas para la herencia y la implementación de contratos en OOP.
    • type: Puede dar nombre a la forma de un objeto, pero no puede ser implementado directamente por una clase usando implements en el mismo sentido. No tienen el mecanismo extends nativo para crear herencia de formas de objeto (aunque puedes combinar tipos usando intersecciones &, que es un concepto diferente).

Guía práctica: ¿Cuándo usar cada uno?

Basándonos en las diferencias anteriores, aquí hay una guía práctica para decidir cuándo usar interfaces y cuándo usar tipos:

Usa interfaces cuando:

  • Defines clases que implementarán la estructura:
interface Repository<T> {
  findAll(): Promise<T[]>;
  findById(id: string): Promise<T | null>;
  save(item: T): Promise<T>;
}

class UserRepository implements Repository<User> {
  // Implementación...
}
  • Creas bibliotecas o APIs públicas que otros desarrolladores pueden necesitar extender:
// En tu biblioteca
interface Theme {
  primaryColor: string;
  secondaryColor: string;
}

// Los consumidores pueden extender
interface CustomTheme extends Theme {
  tertiaryColor: string;
  fontFamily: string;
}
  • Necesitas fusionar declaraciones del mismo nombre:
// Definición base
interface Config {
  apiUrl: string;
}

// En otro archivo o módulo
interface Config {
  timeout: number;
}

// Uso combinado
const config: Config = {
  apiUrl: "https://api.example.com",
  timeout: 3000
};

Usa tipos cuando:

  • Necesitas uniones o intersecciones:
type Result<T> = SuccessResult<T> | ErrorResult;

type UserWithRoles = User & {
  roles: string[];
  permissions: string[];
};
  • Trabajas con tuplas o arrays específicos:
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type Point2D = [number, number];
type RGB = [number, number, number];
type RGBA = [...RGB, number];
  • Necesitas tipos utilitarios o transformaciones:
type Nullable<T> = T | null;
type KeysOf<T> = keyof T;

type UserKeys = KeysOf<User>; // "id" | "name" | "email"
  • Defines alias para tipos primitivos o funciones:
type UserId = string;
type ValidationFunction<T> = (value: T) => boolean;
type EventHandler = (event: Event) => void;

Ejemplo práctico: Modelado de una aplicación

Veamos un ejemplo práctico que muestra cómo combinar interfaces y tipos de manera efectiva:

// Tipos para valores primitivos y uniones
type UserId = string;
type UserRole = "admin" | "editor" | "viewer";
type ValidationResult = "valid" | "invalid" | "pending";

// Interfaces para estructuras de objetos
interface UserBase {
  id: UserId;
  name: string;
  email: string;
}

interface AdminUser extends UserBase {
  role: "admin";
  permissions: string[];
}

interface RegularUser extends UserBase {
  role: "editor" | "viewer";
  department: string;
}

// Tipo para unión de diferentes usuarios
type User = AdminUser | RegularUser;

// Interfaz para servicios (será implementada)
interface UserService {
  getUser(id: UserId): Promise<User | null>;
  validateUser(user: User): ValidationResult;
  updateUser(user: User): Promise<User>;
}

// Implementación concreta
class ApiUserService implements UserService {
  async getUser(id: UserId): Promise<User | null> {
    // Implementación...
    return null;
  }
  
  validateUser(user: User): ValidationResult {
    // Validación basada en el tipo de usuario
    if (user.role === "admin") {
      // Acceso a propiedades específicas de AdminUser
      return user.permissions.length > 0 ? "valid" : "invalid";
    } else {
      // Acceso a propiedades específicas de RegularUser
      return user.department ? "valid" : "invalid";
    }
  }
  
  async updateUser(user: User): Promise<User> {
    // Implementación...
    return user;
  }
}

Consideraciones de compatibilidad

Es importante destacar que interfaces y tipos son estructuralmente compatibles entre sí si sus estructuras coinciden:

interface IPoint {
  x: number;
  y: number;
}

type TPoint = {
  x: number;
  y: number;
};

// Esto es válido - son estructuralmente equivalentes
const p1: IPoint = { x: 10, y: 20 };
const p2: TPoint = p1;

Recomendación general

Una regla práctica que muchos equipos de desarrollo siguen es:

  • Usa interface principalmente cuando estés definiendo la forma de un objeto o el contrato que una clase va a cumplir. Son ideales para la programación orientada a objetos y la definición de estructuras que se implementarán.
  • Usa type cuando necesites dar nombre a cualquier otro tipo (primitivos, uniones simples, tuplas, firmas de funciones) o cuando quieras definir la forma de un objeto de manera más flexible (aunque para formas de objeto simples, la elección entre interface y type es a menudo una cuestión de preferencia o convención del equipo).

Ambas herramientas son esenciales en TypeScript y las verás combinadas a menudo en proyectos reales. La clave es entender sus propósitos principales y sus diferencias para usarlas de forma efectiva.

Aprende TypeScript online

Otros ejercicios de programación de TypeScript

Evalúa tus conocimientos de esta lección Interfaces y su implementación con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Funciones

TypeScript
Test

Reto composición de funciones

TypeScript
Código

Reto tipos especiales

TypeScript
Código

Reto tipos genéricos

TypeScript
Código

Módulos

TypeScript
Test

Polimorfismo

TypeScript
Código

Funciones TypeScript

TypeScript
Código

Interfaces

TypeScript
Puzzle

Funciones puras

TypeScript
Puzzle

Reto namespaces

TypeScript
Código

Funciones flecha

TypeScript
Puzzle

Polimorfismo

TypeScript
Test

Operadores

TypeScript
Test

Conversor de unidades

TypeScript
Proyecto

Funciones flecha

TypeScript
Test

Control de flujo

TypeScript
Código

Herencia

TypeScript
Puzzle

Clases

TypeScript
Puzzle

Proyecto validación de tipado

TypeScript
Proyecto

Clases y objetos

TypeScript
Código

Encapsulación

TypeScript
Test

Herencia

TypeScript
Test

Proyecto sistema de votación

TypeScript
Proyecto

Reto genéricos con clases

TypeScript
Código

Inmutabilidad

TypeScript
Puzzle

Interfaces

TypeScript
Test

Funciones de alto orden

TypeScript
Test

Reto map y filter

TypeScript
Código

Control de flujo

TypeScript
Test

Interfaces

TypeScript
Código

Reto funciones orden superior

TypeScript
Código

Herencia y clases abstractas

TypeScript
Código

Reto tipos mapped

TypeScript
Código

Herencia de clases

TypeScript
Código

Reto funciones puras

TypeScript
Código

Variables y constantes

TypeScript
Puzzle

Introducción a TypeScript

TypeScript
Test

Reto testing unitario

TypeScript
Código

Funciones de primera clase

TypeScript
Puzzle

Clases

TypeScript
Test

OOP y CRUD en TypeScript

TypeScript
Proyecto

Interfaces y su implementación

TypeScript
Código

Tipos genéricos

TypeScript
Test

Namespaces

TypeScript
Test

Operadores y expresiones

TypeScript
Código

Proyecto generador de contraseñas

TypeScript
Proyecto

Reto unión e intersección

TypeScript
Código

Encapsulación

TypeScript
Puzzle

Tipos de unión e intersección

TypeScript
Test

Tipos de unión e intersección

TypeScript
Puzzle

Reto hola mundo en TS

TypeScript
Código

Variables y constantes

TypeScript
Código

Funciones puras

TypeScript
Test

Control de flujo

TypeScript
Código

Introducción a TypeScript

TypeScript
Código

Resolución de módulos

TypeScript
Test

Control de flujo

TypeScript
Puzzle

Reto tipos de utilidad

TypeScript
Código

Reto tipos literales y condicionales

TypeScript
Código

Reto exportar e importar

TypeScript
Código

Propiedades y métodos

TypeScript
Código

Tipos de utilidad

TypeScript
Test

Clases y objetos

TypeScript
Código

Tipos de datos, variables y constantes

TypeScript
Código

Proyecto Minigestor de tareas

TypeScript
Proyecto

Operadores

TypeScript
Puzzle

Funciones flecha y contexto

TypeScript
Código

Proyecto Inventario de productos

TypeScript
Proyecto

Funciones

TypeScript
Puzzle

Reto type aliases

TypeScript
Código

Funciones de alto orden

TypeScript
Puzzle

Funciones y parámetros tipados

TypeScript
Código

Tipos literales

TypeScript
Puzzle

Reto enums

TypeScript
Código

Tipos de utilidad

TypeScript
Puzzle

Modificadores de acceso y encapsulación

TypeScript
Código

Polimorfismo

TypeScript
Puzzle

Tipos genéricos

TypeScript
Puzzle

Reto módulos

TypeScript
Código

Tipos literales

TypeScript
Test

Inmutabilidad

TypeScript
Test

Proyecto Generator de datos

TypeScript
Proyecto

Variables y constantes

TypeScript
Test

Funciones de primera clase

TypeScript
Test

Todas las lecciones de TypeScript

Accede a todas las lecciones de TypeScript y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Typescript

TypeScript

Introducción Y Entorno

Instalación Y Configuración De Typescript

TypeScript

Introducción Y Entorno

Tipos De Datos, Variables Y Constantes

TypeScript

Sintaxis

Operadores Y Expresiones

TypeScript

Sintaxis

Control De Flujo

TypeScript

Sintaxis

Funciones Y Parámetros Tipados

TypeScript

Sintaxis

Funciones Flecha Y Contexto

TypeScript

Sintaxis

Enums

TypeScript

Sintaxis

Type Aliases Y Aserciones De Tipo

TypeScript

Sintaxis

Clases Y Objetos

TypeScript

Programación Orientada A Objetos

Interfaces Y Su Implementación

TypeScript

Programación Orientada A Objetos

Modificadores De Acceso Y Encapsulación

TypeScript

Programación Orientada A Objetos

Herencia Y Clases Abstractas

TypeScript

Programación Orientada A Objetos

Polimorfismo

TypeScript

Programación Orientada A Objetos

Decoradores Básicos

TypeScript

Programación Orientada A Objetos

Propiedades Y Métodos

TypeScript

Programación Orientada A Objetos

Inmutabilidad

TypeScript

Programación Funcional

Funciones Puras Y Efectos Secundarios

TypeScript

Programación Funcional

Funciones De Primera Clase

TypeScript

Programación Funcional

Funciones De Alto Orden

TypeScript

Programación Funcional

Conceptos Básicos E Inmutabilidad

TypeScript

Programación Funcional

Funciones De Primera Clase Y Orden Superior

TypeScript

Programación Funcional

Composición De Funciones

TypeScript

Programación Funcional

Métodos Funcionales De Arrays (Map, Filter, Reduce)

TypeScript

Programación Funcional

Tipos Literales Y Tipos Condicionales

TypeScript

Tipos Intermedios Y Avanzados

Tipos Genéricos Básicos

TypeScript

Tipos Intermedios Y Avanzados

Tipos De Unión E Intersección

TypeScript

Tipos Intermedios Y Avanzados

Tipos De Utilidad (Partial, Required, Pick, Etc)

TypeScript

Tipos Intermedios Y Avanzados

Unknown, Never Y Tipos Especiales

TypeScript

Tipos Intermedios Y Avanzados

Tipos Mapped

TypeScript

Tipos Intermedios Y Avanzados

Genéricos Con Clases E Interfaces

TypeScript

Tipos Intermedios Y Avanzados

Módulos

TypeScript

Namespaces Y Módulos

Namespaces

TypeScript

Namespaces Y Módulos

Resolución De Módulos

TypeScript

Namespaces Y Módulos

Exportación E Importación De Módulos

TypeScript

Namespaces Y Módulos

Introducción A Módulos

TypeScript

Namespaces Y Módulos

Testing Unitario En Typescript

TypeScript

Testing

Accede GRATIS a TypeScript y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Definir contratos de objeto con interface.
  • Implementar interfaces en clases con implements.
  • Implementar múltiples interfaces en una clase.
  • Extender interfaces para reutilizar contratos.
  • Comprender la diferencia básica entre interface y type.