Fusión de declaraciones de interfaz en TypeScript

En nuestra publicación anterior sobre TypeScript Mixins, hablamos brevemente sobre la combinación de declaraciones en TypeScript. En esta serie de publicaciones, profundizaremos un poco más, comenzando con las interfaces con combinación de declaraciones de interfaz.
¿Qué es la fusión de declaraciones?
La fusión de declaraciones es cuando el compilador de TypeScript fusiona dos o más tipos en una declaración siempre que tengan el mismo nombre.
TypeScript permite la fusión entre varios tipos, como interface
with interface
, enum
with enum
, namespace
with namespace
, etc. Una fusión notable que no está permitida es class
with class
merging. Si quieres una funcionalidad como esa, prueba mixins.
Comencemos con interface
la interface
fusión observando un ejemplo:
interface Person { name: string;}interface Person { age: number;}interface Person { height: number;}class Employee implements Person { name = "Mensah" age = 100; height = 40}const employee = new Employee();console.log(employee) // {name: "Mensah", age: 100, height: 40}
Dado que todas las interfaces se declararon con el mismo nombre, Person
se fusionan en una definición para que la Employee
clase contenga las propiedades de todas las interfaces.
Mismos nombres de propiedades en interfaces (no funciones)
Si alguna de las interfaces que se van a fusionar contiene el mismo nombre de propiedad y esa propiedad no es una función, entonces las type
propiedades deben ser las mismas o de lo contrario el compilador generará un error.
interface Person { name: string; zipCode: string;}interface Person { age: number; zipCode: string; // acceptable}interface Person { zipCode: number; // error}
Mismos nombres de propiedades en interfaces (funciones)
Cuando los elementos en las interfaces fusionadas son funciones y tienen el mismo nombre, se sobrecargan, es decir, dependiendo del type
argumento pasado, se llamará la función adecuada.
interface Person { speak(words: string);}interface Person { speak(words: number);}const person: Person = { speak: (wordsOrNum) = wordsOrNum}console.log(person.speak("Hi")) // speak(words: string) is usedconsole.log(person.speak(2)) // speak(words: number) is used
Cuando se fusionan interfaces que contienen funciones con la misma firma, las funciones de las últimas interfaces declaradas aparecen en la parte superior de la interfaz fusionada y las funciones declaradas en la primera interfaz aparecen debajo.
interface Person { speak(words:string);}interface Person { speak(words: any);}interface Person { speak(words: number); speak(words: boolean);}// This is how the final merged interface looks likeinterface Person { // functions in the last interface appear at the top speak(words: number); speak(words: boolean); // function in the middle interface appears next speak(words: any):number; // function in the first interface appears last speak(words: string):string;}
La razón de esto es que las interfaces declaradas posteriormente tienen una mayor precedencia sobre las interfaces declaradas inicialmente. Por lo tanto, en nuestro ejemplo anterior, speak(words: string)
nunca se llamará porque en la Person
interfaz fusionada final, speak(words: any):number
viene antes speak(words: string):string
y, dado que any
puede representar cualquier tipo, se llama incluso si a string
se pasa como un argument
.
Para probar esto, cuando pase el cursor sobre la per
variable en el código a continuación, se mostrará const per: number
y no, const per: string
aunque estemos pasando un string
argumento.
const per = person.speak("bacon");
Esto es cierto para todas las interfaces, excepto cuando los parámetros de funciones con el mismo nombre tienen un literal de cadena como type
. Sigue el mismo orden descrito anteriormente, pero las funciones con tipos de literales de cadena tienen mayor precedencia y, por lo tanto, aparecen en la parte superior.
Vale la pena señalar que los literales de cadena en interfaces posteriores aparecerán antes que las interfaces iniciales, como se explicó anteriormente.
interface Person { speak(words: number); speak(words: "World!"); // string literal type}interface Person { speak(words: "Hello"); // string literal type}interface Person { speak(words: string);}// merged interface output.interface Person { // string literals are given precedence speak(words: "Hello"); speak(words: "World!"); // the rest of the functions are arranged using the same rules. speak(words: string); speak(words: number);}
Eso es todo. Espero que te haya resultado útil.
Deja una respuesta