Búsqueda de sitios web

javascript - Restringir métodos de clase de TypeScript que implementan una interfaz


Actualmente, si creo una clase que implementa una interfaz, la clase creada tendrá todos los métodos que no están incluidos en la interfaz. Aquí hay un ejemplo:

interface ExampleTypes {
  alpha();
}

class Example implements ExampleTypes {
  alpha () {
    return true
  }
  beta () {
    return true
  }
}

Estoy buscando una manera de restringir los métodos que una clase determinada puede tener.

Esto es algo que también intenté:

class ExampleSource {
  alpha () {
    return true
  }
}

class Example implements Partial<ExampleSource> {
  alpha () {
    return true
  }
  beta () {
    return true
  }
}

Y esto:

class ExampleSource {
  alpha () {
    return true
  }
}

class Example implements ExampleSource {
  alpha () {
    return true
  }
  beta () {
    return true
  }
}

Lo cual no es intuitivo. Me gustaría que beta no estuviera permitido en Example.

Esta es la funcionalidad que funciona pero usando una función y no una clase:

interface ExampleType {
  alpha?();
  beta?();
}

Este es el valor:

function Example(): ExampleType {
  return {
    alpha: () => true,
  };
}

Esto genera un error de TypeScript:

function Example(): ExampleType {
  return {
    alpha: () => true,
    meow: () => true,
  };
}

Idealmente, puedo tener esta misma funcionalidad pero con clases.

Respuesta #1

Es una solicitud extraña, ya que tener métodos adicionales no impedirá que uses la clase como si no estuvieran allí. TypeScript realmente no tiene mucho soporte para excluir propiedades o métodos adicionales de los tipos; es decir, actualmente no hay soporte directo para tipos exactos como se solicita en microsoft/TypeScript#12936.

Afortunadamente, puedes obtener este comportamiento de alguna manera haciendo un condicional autorreferencial, tipo mapeado:

type Exactly<T, U> = { [K in keyof U]: K extends keyof T ? T[K] : never };

Si declaras que un tipo U es Exactly<T, U>, se asegurará de que U coincida con T, y que cualquier propiedad extra sea del tipo never. Los tipos autorreferenciales/recursivos/circulares no siempre se compilan, pero en este caso solo te estás refiriendo a keyof U dentro de la definición de U, lo cual está permitido.

Vamos a intentarlo:

interface ExampleTypes {
  alpha(): boolean; // adding return type
}

// notice the self-reference here
class Example implements Exactly<ExampleTypes, Example> {
  // okay
  alpha() {
    return true;
  }

  // error!  Type '() => boolean' is not assignable to type 'never'.
  beta() {
    return true;
  }
}

¡Parece que funciona!

Artículos relacionados