javascript - interfaz - interface node js
¿Cómo funcionan las interfaces mecanografiadas con firmas de construcción? (5)
Bueno, una interfaz con una firma de construcción no debe ser implementada por ninguna clase (a primera vista, esto podría parecer extraño para chicos con C # / Java como yo, pero dale una oportunidad). Es ligeramente diferente.
Por un momento piense en ello como una interfaz con una firma de llamada (como @FunctionalInterface en el mundo de Java). Su propósito es describir un tipo de función ... clase de. Se supone que la firma descrita debe ser satisfecha por un objeto de función ... pero no solo por cualquier función de alto nivel o método. Debería ser una función que sepa cómo construir un objeto, una función a la que se llama cuando se utiliza una new
palabra clave.
¡Entonces una interfaz con una firma de construcción define la firma de un constructor! El constructor de su clase que debe cumplir con la firma definida en la interfaz (piénselo como el constructor implementa la interfaz). ¡Es como un constructor o una fábrica!
Aquí hay un pequeño fragmento de código que intenta demostrar el uso más común:
interface ClassicInterface { // old school interface like in C#/Java
method1();
...
methodN();
}
interface Builder { //knows how to construct an object
// NOTE: pay attention to the return type
new (myNumberParam: number, myStringParam: string): ClassicInterface
}
class MyImplementation implements ClassicInterface {
// The constructor looks like the signature described in Builder
constructor(num: number, s: string) { } // obviously returns an instance of ClassicInterface
method1() {}
...
methodN() {}
}
class MyOtherImplementation implements ClassicInterface {
// The constructor looks like the signature described in Builder
constructor(n: number, s: string) { } // obviously returns an instance of ClassicInterface
method1() {}
...
methodN() {}
}
// And here is the polymorphism of construction
function instantiateClassicInterface(ctor: Builder, myNumberParam: number, myStringParam: string): ClassicInterface {
return new ctor(myNumberParam, myStringParam);
}
// And this is how we do it
let iWantTheFirstImpl = instantiateClassicInterface(MyImplementation, 3.14, "smile");
let iWantTheSecondImpl = instantiateClassicInterface(MyOtherImplementation, 42, "vafli");
Tengo problemas para determinar cómo funcionan los desarrolladores de interfaces. Podría estar totalmente mal entendiendo algo. Pero he buscado respuestas durante un buen rato y no puedo encontrar nada relacionado con esto.
¿Cómo implemento la siguiente interfaz en una clase de TypeScript?
interface MyInterface {
new ( ... ) : MyInterface;
}
Anders Hejlsberg crea una interfaz que contiene algo similar a esto en este video (alrededor de 14 minutos). Pero por mi vida no puedo implementar esto en una clase.
Probablemente esté malinterpretando algo, ¿qué no voy a obtener?
EDITAR:
Para aclarar. Con "nuevo (...)" quise decir "cualquier cosa". Mi problema es que no puedo obtener ni siquiera la versión más básica de esto funcionando:
interface MyInterface {
new () : MyInterface;
}
class test implements MyInterface {
constructor () { }
}
Esto no está compilando para mí Obtengo "Class ''test" declara la interfaz "MyInterface" pero no la implementa: Escriba'' MyInterface ''requiere una firma de construcción, pero Type'' test ''no tiene una "cuando intenta compilarla.
EDITAR:
Entonces, después de investigar esto un poco más, teniendo en cuenta los comentarios.
interface MyInterface {
new () : MyInterface;
}
class test implements MyInterface {
constructor () => test { return this; }
}
No es un TypeScript válido y esto no resuelve el problema. No puede definir el tipo de devolución del constructor. Devolverá "prueba". La firma de lo siguiente: class test {constructor () {}} Parece ser "nueva () => prueba" (obtenida al pasar el mouse sobre "clase" en el editor en línea con solo ese código pegado). Y esto es lo que queremos y lo que pensé que sería.
¿Alguien puede dar un ejemplo de esto o algo similar donde realmente está compilando?
EDITAR (nuevamente ...):
Así que podría haberme imaginado por qué es posible definir esto en una interfaz pero no es posible implementarlo en una clase de TypeScript. Lo siguiente funciona:
var MyClass = (function () {
function MyClass() { }
return MyClass;
})();
interface MyInterface {
new () : MyInterface;
}
var testFunction = (foo: MyInterface) : void => { }
var bar = new MyClass();
testFunction(bar);
Entonces, ¿esta es solo una característica de TypeScript que le permite interactuar con javascript? ¿O es posible implementarlo en TypeScript sin tener que implementar la clase con javascript?
Desde una perspectiva de diseño, no es habitual especificar los requisitos del constructor en una interfaz. La interfaz debe describir las operaciones que puede realizar en un objeto. Se debe permitir que las diferentes clases que implementan la interfaz requieran diferentes parámetros de constructor si es necesario.
Por ejemplo, si tuviera una interfaz:
interface ISimplePersistence {
load(id: number) : string;
save(id: number, data: string): void;
}
Es posible que tenga implementaciones para almacenar los datos como una cookie, que no necesita parámetros de constructor, y una versión que almacena los datos en una base de datos, que necesita una cadena de conexión como parámetro de constructor.
Si todavía quieres definir constructores en una interfaz, hay una forma sucia de hacerlo, que solía responder a esta pregunta:
Interfaces con firmas de construcción no tipo de comprobación
En mi búsqueda de la misma pregunta, fui buscando cómo el Equipo de TypeScript hizo eso ...
Están declarando una interfaz y luego una variable con un nombre que coincide exactamente con el nombre de la interfaz. Esta es también la forma de escribir funciones estáticas.
Ejemplo de lib.d.ts
:
interface Object {
toString(): string;
toLocaleString(): string;
// ... rest ...
}
declare var Object: {
new (value?: any): Object;
(): any;
(value: any): any;
// ... rest ...
}
Intenté eso y funciona como encanto.
Las firmas de construcción en las interfaces no son implementables en las clases; solo sirven para definir las API JS existentes que definen una función ''nueva''. Aquí hay un ejemplo que involucra interfaces new
firmas que funciona:
interface ComesFromString {
name: string;
}
interface StringConstructable {
new(n: string): ComesFromString;
}
class MadeFromString implements ComesFromString {
constructor (public name: string) {
console.log(''ctor invoked'');
}
}
function makeObj(n: StringConstructable) {
return new n(''hello!'');
}
console.log(makeObj(MadeFromString).name);
Esto crea una restricción real para lo que puede invocar makeObj
con:
class Other implements ComesFromString {
constructor (public name: string, count: number) {
}
}
makeObj(Other); // Error! Other''s constructor doesn''t match StringConstructable
Para lograr el comportamiento deseado, puede utilizar Decorators , aunque probablemente no sea para lo que se supone que se debe usar.
Esta
interface MyInterface {
new ();
}
function MyInterfaceDecorator(constructor: MyInterface) {
}
@MyInterfaceDecorator
class TestClass {
constructor () { }
}
compila sin problema Por el contrario, la siguiente definición para TestClass
// error TS2345: Argument of type ''typeof TestClass'' is not assignable to parameter of type ''MyInterface''.
@MyInterfaceDecorator
class TestClass {
constructor (arg: string) { }
}
no compilará