static y readonly: propiedades de clase
Las propiedades y métodos estáticos pertenecen a la clase, no a las instancias. Son perfectos para factories, contadores compartidos y constantes de configuración.
static: pertenece a la clase
Una propiedad o método static existe en la clase misma, no en cada instancia. Se accede usando el nombre de la clase, no this:
class Matematica {
static PI = 3.14159265;
static circunferencia(radio: number): number {
return 2 * Matematica.PI * radio;
}
static area(radio: number): number {
return Matematica.PI * radio ** 2;
}
}
// Se accede por la clase, no por una instancia
console.log(Matematica.PI); // 3.14159265
console.log(Matematica.circunferencia(5)); // 31.415...
console.log(Matematica.area(3)); // 28.274...
// ❌ No se accede por instancia
// const m = new Matematica();
// m.PI // Error: Property 'PI' does not exist on instance3.14159265
31.41592653589793
28.274333882308138Math.random(), Array.isArray(), Object.keys(), JSON.parse() — todos son métodos estáticos de sus respectivas clases. No necesitas crear new Math() para usarlos.
Casos de uso: factories y contadores
Los usos más comunes de static son: contadores compartidos entre instancias, métodos factory y utilidades de la clase:
class Conexion {
private static totalConexiones: number = 0;
private static readonly MAX_CONEXIONES = 10;
private id: number;
private url: string;
private constructor(url: string) {
Conexion.totalConexiones++;
this.id = Conexion.totalConexiones;
this.url = url;
}
// Factory method estático
static crear(url: string): Conexion {
if (Conexion.totalConexiones >= Conexion.MAX_CONEXIONES) {
throw new Error("Límite de conexiones alcanzado");
}
return new Conexion(url);
}
static getTotal(): number {
return Conexion.totalConexiones;
}
describir(): string {
return `Conexión #${this.id} → ${this.url}`;
}
}
const c1 = Conexion.crear("https://api.ejemplo.com");
const c2 = Conexion.crear("https://db.ejemplo.com");
console.log(c1.describir()); // "Conexión #1 → https://api.ejemplo.com"
console.log(c2.describir()); // "Conexión #2 → https://db.ejemplo.com"
console.log(Conexion.getTotal()); // 2Conexión #1 → https://api.ejemplo.com
Conexión #2 → https://db.ejemplo.com
2Marcar el constructor como private y exponer un método estático crear() o from() da control total sobre cómo se crean instancias. Este patrón es muy común en librerías como Date.now() o Buffer.from().
readonly en propiedades estáticas
Combinar static con readonly crea constantes de clase que no pueden cambiar una vez definidas:
class Config {
static readonly APP_NAME = "MiApp";
static readonly VERSION = "2.1.0";
static readonly MAX_INTENTOS = 3;
static readonly TIEMPO_ESPERA_MS = 5000;
static describir(): string {
return `${Config.APP_NAME} v${Config.VERSION}`;
}
}
console.log(Config.APP_NAME); // "MiApp"
console.log(Config.describir()); // "MiApp v2.1.0"
// ❌ Error: Cannot assign to 'APP_NAME' because it is a read-only property
// Config.APP_NAME = "OtraApp";
// Uso en lógica de la app
function intentarConexion(url: string): void {
for (let i = 0; i < Config.MAX_INTENTOS; i++) {
console.log(`Intento ${i + 1} de ${Config.MAX_INTENTOS}...`);
// lógica de conexión...
}
}
intentarConexion("https://api.ejemplo.com");MiApp
MiApp v2.1.0
Intento 1 de 3...
Intento 2 de 3...
Intento 3 de 3...Métodos estáticos como utilidades
Los métodos estáticos son ideales para lógica que no necesita estado de instancia — transformaciones, validaciones y helpers:
class Cadena {
static capitalizar(texto: string): string {
if (!texto) return texto;
return texto[0].toUpperCase() + texto.slice(1).toLowerCase();
}
static truncar(texto: string, max: number): string {
if (texto.length <= max) return texto;
return texto.slice(0, max - 3) + "...";
}
static slugify(texto: string): string {
return texto
.toLowerCase()
.normalize("NFD")
.replace(/[̀-ͯ]/g, "")
.replace(/s+/g, "-")
.replace(/[^a-z0-9-]/g, "");
}
}
console.log(Cadena.capitalizar("hola mundo")); // "Hola mundo"
console.log(Cadena.truncar("Una cadena muy larga que debe cortarse", 20)); // "Una cadena muy la..."
console.log(Cadena.slugify("Programación en TypeScript")); // "programacion-en-typescript"Hola mundo
Una cadena muy la...
programacion-en-typescript- Usa
staticcuando la lógica no depende del estado de una instancia específica - Usa
static readonlypara constantes que pertenecen a la clase entera - Los métodos factory estáticos dan nombres descriptivos a diferentes formas de construir objetos
- No abuses de clases estáticas como sustituto de módulos — un simple objeto o función exportada es más simple