Recently reviewed the foundation to see the Learning Typescript this book, opened to learn, found a lot of knowledge, in this record.
Object-oriented programming
The principle of SOLID
There are five considerations for object-oriented programming with Typescript, known simply as the “SOLID” principles
- Single Responsibility Principle (SRP): States that software components (functions, classes, modules) must focus on a single task (with only a single responsibility)
- Open/closed principle (OCP): indicates that software must always be designed with an eye to possible evolution (extensibility), but that the program must evolve with minimal modification of existing code (closed to existing changes)
– Richter substitution principle (LSP): indicates that any class in a program can be replaced by another class as long as it inherits the same interface. After the replacement is complete, no additional working procedures are required to run as before. – Interface isolation principle (ISP): indicates that very large interfaces should be broken down into more specific interfaces so that clients only need to care about the interfaces they need. – Dependency Reversal principle (DIP): indicates that a method should comply with the concept of relying on an abstraction (interface) rather than an instance (class). Write a class in Typesciript that looks like this:
class Person{
public name: string;
public surname: string;
public email: string;
constructor(name: string, surname: string, email: string){
this.email = email;
this.name = name;
this.surname = surname;
}
greet(){
alert("hello"); }}var p : Person = new Person("liming"."li"."[email protected]");
Copy the code
If we want to validate the email format, adding code to Person would make the Person class very large. We can isolate the email abstraction into a single class, which illustrates the first principle of single responsibility.
class Email{
public email: string;
constructor(email: string){
if(this.validateEmail(email)){
this.email = email
}else{
throw new Error("Invalid email!")}}private validateEmail(email: string){
var re = '/\S+@\S+\.\S+/';
return re.test(email)
}
}
class Person{
public name: string;
public surname: string;
public email: Email;
constructor(name: string, surname: string, email: string){
this.email = email;
this.name = name;
this.surname = surname;
}
greet(){
alert("hello"); }}Copy the code
In the object-oriented process, there are some relationships between classes, such as association, aggregation, composition, inheritance, mixing, and so on. Instead of introducing their concepts, I will introduce generic classes and generic constraints
A generic class
Generic classes, like generic functions, can introduce a lot of repetitive code. Let’s start with a class
There is oneUser
Class and oneNotGenericUserRepository
This is a class that gets a list of users and passes it to a JSON file. This is a different class when we want to get a meeting, or a list of songsGenericRepository
Classes are overridden, and you can use generic classes. As follows:
Sometimes we need generic constraints, as in the example above, and the new requirement is to add some changes to validate data requested through Ajax:
success: (data) = >{
var list: T[]
varitems = <T[]>data.items for(let i=0; i<items.length; If (items[I].isValid()){// validates //... } } resolve(list) }Copy the code
We can write a validation interface that constrains generics:
class User implements ValidatableInterface{
public name: string
public password: string
constructor(name: string, password: string){
this.name = name
this.password = password
}
public isValid(){
// ...
return true}}class Talk implements ValidatableInterface{
public name: string
constructor(name: string, password: string){
this.name = name
}
public isValid(){
// ...
return true}}class NotGenericUserRepository<T extends ValidatableInterface>{
private _url: string
constructor(url: string){
this._url = url
}
public getAsync(){
return new Promise((resolve: (users: T[]) => void. reject) = > {
$.ajax({
url: this._url,
type: "GET".dataType: "JSON".success: (data) = >{
var list: T[]
varitems = <T[]>data.items for(let i=0; i<items.length; i++){ if(items[i].isValid()){ list.push(items[i]) } } resolve(list) }, error: (e)=>{ reject(e) } }) }) } }class User implements ValidatableInterface{ public name: string public password: string constructor(name: string, password: string){ this.name = name this.password = password } public isValid(){ // ... return true } } class Talk implements ValidatableInterface{ public name: string constructor(name: string, password: string){ this.name = name } public isValid(){ // ... return true } } class NotGenericUserRepository<T extends ValidatableInterface>{ private _url: string constructor(url: string){ this._url = url } public getAsync(){ return new Promise((resolve: (users: T[]) => void. reject) => { $.ajax({ url: this._url, type: "GET", dataType: "JSON", success: (data)=>{ var list: T[] var items = <T[]>data.items for(let i=0; i<items.length; i++){ if(items[i].isValid()){ list.push(items[i]) } } resolve(list) }, error: (e)=>{ reject(e) } }) }) } }Copy the code
The new operation in generics
To create a new object in code, we need to declare that the generic T has a constructor. This means we need to use type: {new() :T; } substitution type: T